---
--类名: FieldManager.lua
--创建日期: 2017-3-9
--创建人: 陈小虎
--功能描述:
--修改内容:
--修改日期: 2017-6-9
--修改人: galileoliu
--修改备注:
--

local Mercenary = import("..models.Mercenary")
local Character = import("..models.Character")
local MapUpdate = import("..models.vo.MapUpdate")
local Vector = require("app.utils.Vector")

local updateQueueCharacterInterval = 0.3

local ADJUST_DISTANCE = 500
local MERCENARY_ADJUST_DISTANCE = 1500 -- 随从的调整距离设置大一点，否则当任务随从过多时会出现问题

local NodeGetPositionFunc = cc.Node.getPosition
local NodeSetPositionFunc = cc.Node.setPosition
local NodeGetPositionXFunc = cc.Node.getPositionX
local NodeSetPositionXFunc = cc.Node.setPositionX
local NodeGetPositionYFunc = cc.Node.getPositionY
local NodeSetPositionYFunc = cc.Node.setPositionY
local NodeIsVisibleFunc = cc.Node.isVisible
local NodeSetVisibleFunc = cc.Node.setVisible
local NodeToWorldPosition = cc.Node.toWorldPosition
local NodeGetScaleFunc = cc.Node.getScale
local NodeSetScaleFunc = cc.Node.setScale
local NodeGetScaleXFunc = cc.Node.getScaleX
local NodeSetScaleXFunc = cc.Node.setScaleX
local NodeGetScaleYFunc = cc.Node.getScaleY
local NodeSetScaleYFunc = cc.Node.setScaleY

local ToString = tostring
local ToNumber = tonumber
local MathFloor = math.floor
local MathAbs = math.abs

local TeamManager_updateTeamPosition = TeamManager.updateTeamPosition
local NpcManager_updateNpcPlayEvents = NpcManager.updateNpcPlayEvents
local DungeonManager_updateFrame = DungeonManager.updateFrame
local MapManager_updateFrame = MapManager.updateFrame
local DelayStack_updateFrame = DelayStack.updateFrame
local NpcManager_updateNpcLower = NpcManager.updateNpcLower
local BattleManager_updateDarkThunderBattle = BattleManager.updateDarkThunderBattle

local TeamModel

local FieldManager = class("FieldManager")

function FieldManager:ctor()
    cc(self):addComponent("components.behavior.EventProtocol"):exportMethods()

    self:initData()

    self._debugUserTimeCount = 0
    self._debugUserCount = 0
end

function FieldManager:initData()
    self._mapUpdate = MapUpdate.new()
    self._queueEntityInfos = {}    -- 加入队列中即将创建avatar的玩家信息
    self._lastUpdateQueueCharacterTime = 0

    self._mapCharacters = {}
    self._lionHornCharacters = {}     -- 狮心号角队伍角色
    self._theatreMyChatacters = {}      -- 歌剧院队伍角色
    self._theatreEnemyChatacters = {}      -- 歌剧院队伍角色


    self._followMercenarys = {}
    self._selfTaskFollowMercenarys = {}
    self._teamTaskFollowMercenarys = {}

    self._lastCharacterX = 0
    self._hidingCharacters = false

    self._followNpcs = {}

    self.lastReportPosStatus = Enums.status.idle
end

function FieldManager:clear()
    self._myCharacter = nil
    self._puppetCharacter = nil
    self._mapCharacters = {}
    self._chessCharacter = nil     -- 星空谜棋，对手角色
    self._lionHornCharacters = {}     -- 狮心号角队伍角色
    self._theatreMyChatacters = {}      -- 歌剧院队伍角色
    self._theatreEnemyChatacters = {}      -- 歌剧院队伍角色

    self:clearFollowMercenarys()
    self:removeSelfTaskFollowMercenary()
    self:removeTeamTaskFollowMercenary()

    self._lastCharacterX = 0
    self._hidingCharacters = false

    self:clearFollowNpc()

    -- self._mapUpdate = MapUpdate.new()
    self._queueEntityInfos = {}
    self._lastUpdateQueueCharacterTime = 0
    self._notifyPackect = nil

    self.lastReportPosStatus = Enums.status.idle
end

function FieldManager:init()
    TeamModel = app:getInst("TeamModel")
    self:initWeatherSystem()

    -- 添加切换到后台事件
    EM:on("OnAppEnterBackground", function()
        if TeamModel:isWithTeam() then return end
        self:moveControl(Enums.MoveFlag.stop)
    end)
end

function FieldManager:getMapUpdate()
    return self._mapUpdate
end

function FieldManager:getSelfEntity()
    return self._mapUpdate:getSelf()
end

function FieldManager:getOtherEntities()
    return self._mapUpdate:getOtherEntities()
end

function FieldManager:getSelfBaseInfo()
    if self:getSelfEntity() then
        return self:getSelfEntity():getInfo()
    end
end

function FieldManager:getEntityById(id)
    id = tonumber(id)
    local entity = self:getSelfEntity()
    if entity and entity:getId() == id then
        return entity
    else
        entity = self._mapUpdate:getOtherEntityById(id)
        return entity
    end
end

function FieldManager:getBaseInfoById(id)
    local entity = self:getEntityById(id)
    if entity then
        return entity:getInfo()
    end
end

function FieldManager:getMyCharacter()
    return self._myCharacter
end

function FieldManager:updateMyCharacterUserBaseInfo(baseInfo)
    if self._myCharacter then
        self._myCharacter:setUserBaseInfo(baseInfo)
    end
end

function FieldManager:setOwnerX(ox)
    self._ownerX = ox
end

function FieldManager:getOwnerX()
    return self._ownerX or 0
end

function FieldManager:updateMapCharacters()
    if MapManager:isChangeMap() then return end

    self:doUpdateMapCharacters()
end

function FieldManager:doUpdateMapCharacters()
    if not self._mapUpdate:isThisMap(MapManager:getMapId()) then return end

    -- 更新玩家自己
    local selfEntity = self:getSelfEntity()
    local info = selfEntity:getInfo()
    if info and self._myCharacter then
        -- 更新随从的avatar
        self:updateCharacterFollowMercenary(info.partners, self._myCharacter)
        -- 更新玩家自己的任务随从avatar
        self:updateSelfTaskFollowMercenary(info)
        -- 更新行为icon
        self:updateCharacterBehavior(self._myCharacter, selfEntity)
        -- 更新左上角血量
        self:updateMyBlood(self._myCharacter, selfEntity)
        -- 更新玩家所在的区域
        self:updateCharacterFieldTag(self._myCharacter, selfEntity)
        -- 更新玩家的坐骑（玩家采集或者剧情的时候可能会下坐骑,所以这里放在外面更新）
        self:updateMount(self._myCharacter, info)
        -- 更新玩家速度 (从跟随变成未跟随时，需要更新速度，所以这里放在外面更新)
        self:updateSpeed(self._myCharacter, info)

        if selfEntity:isBaseInfoUpdate() then
            self:updateAvatar(self._myCharacter, info)
            self:updateCharacterUpHead(self._myCharacter,info)
            selfEntity:setBaseInfoUpdate(false)
        end
        -- 修正位置
        if not TeamModel:isWithTeam() then
            self:resetAllCharacterPos(self._myCharacter, selfEntity)
        end
        -- 更新玩家名字颜色
        if app:getInst("DynastyMapModel"):isDynastyMap() or  UD.csGuildWarData:isCSGuildWarPrepareMap() then
            self:updateCharacterDynastyShow(self._myCharacter, selfEntity)
        elseif TeamManager:isEnitityInMyTeam(UD:getUid()) then
            self._myCharacter:toTeamColor()
        else
            self._myCharacter:toNormalColor()
        end
    end

    -- 公会战逻辑处理
    if app:getInst("DynastyMapModel"):isDynastyMap() then
        -- 删除其他玩家的位置节点
        app:sendMsg("DynastyMapController", "removeAllTeamNodes")
        -- 更新 我 的队伍人数
        local num = TeamModel:getMemberNum()
        app:sendMsg("DynastyMapController", "setMyTeamCount", num)
    end

    -- 更新其他玩家
    -- 删除不在视野中的其他玩家的avatar
    local characterToDelete = {}
    for uid, character in pairs(self._mapCharacters) do
        if self:getEntityById(uid) == nil then
            table.insert(characterToDelete, uid)
        end
    end
    for _, uid in ipairs(characterToDelete) do
        self:deleteEntityInfoFromQueue(uid)
        self:removeMapCharacterByUid(uid)
    end

    -- 更新在视野中的其他玩家的avatar
    for _, entity in pairs(self:getOtherEntities()) do
        self:updateSingleCharacter(entity)
    end

    self:updateTeamTaskFollowMercenary()
end

function FieldManager:updateCharacterFromEntity(character,entity)
    if entity:isFaceToLeft() then
        character:faceToDirectionNotPlayAction("left")
    else
        character:faceToDirectionNotPlayAction("right")
    end

    local tx = MathFloor(entity:getX())
    if entity.status == Enums.status.idle then
        character:setTargetX(tx)
    elseif entity.status == Enums.status.run then
        if entity:isFaceToLeft() then
            tx = character:getLineMinX()
        elseif entity:isFaceToRight() then
            tx = character:getLineMaxX()
        end
        character:setTargetX(tx)
    end
    -- 修正位置
    self:resetAllCharacterPos(character, entity)
end

-- 修正 非跟随玩家 的位置（人物当前的位置和服务器给定的位置差距过大时 修正）
function FieldManager:resetAllCharacterPos(character, entity)
    local curPosXFloat = NodeGetPositionXFunc(character)
    local curPosX = MathFloor(curPosXFloat)
    local tx = MathFloor(entity:getX())

    if MathAbs(curPosX - tx) <= ADJUST_DISTANCE then return end

    if character:isMySelf() then -- 移动摄像机
        self:adjustSelfToFixedPosition(tx)
        if entity.status == Enums.status.idle then -- 会设置目标点
            self:adjustSelfToFixedPosition(tx) 
        elseif entity.status == Enums.status.run then -- 不设置目标点
            character:showLocationXNotTarget(tx)
            MapManager:initCamera()
            MapManager:resetMapFocus()
        end
    else
        character:showLocationX(tx) 
        if entity.status == Enums.status.idle then -- 会设置目标点
            character:showLocationX(tx) 
        elseif entity.status == Enums.status.run then
            character:showLocationXNotTarget(tx) -- 不设置目标点
        end
     end
end

function FieldManager:updateSingleCharacter(entity)
    if not entity then return end
    local entityId = entity:getId()
    local character = self:getCharacterByUid(entityId)
    local info = entity:getInfo()
    if info then
        if not character then
            self:addUserToQueue({entityId = entityId,prior = false,})
        else
            -- 更新随从的avatar
            self:updateCharacterFollowMercenary(info.partners,character)
        end
    end

    if character then
        local colorFunc 
        local isCharacterInMyTeam = TeamManager:isEnitityInMyTeam(entityId)
        if isCharacterInMyTeam then
            -- character:toTeamColor()
            colorFunc = handler(character, character.toTeamColor)
            -- 在我的队伍中的角色通过TeamManager来进行位置同步
            if entityId == TeamModel:getLeaderUid() then
                MapManager:getMap():changeLine(character,character.LINE_2)
                self:updateCharacterFromEntity(character,entity)
            end
        else
            -- character:toNormalColor()
            colorFunc = handler(character, character.toNormalColor)
            -- character:backToNormalSpeed()
            local line = character:getOriginalLine()
            if line and character:getLine() ~= line then
                MapManager:getMap():changeLine(character,line)
            end
            self:updateCharacterFromEntity(character,entity)
        end
        -- 更新玩家的行为icon
        self:updateCharacterBehavior(character, entity)
        -- 更新玩家所在的区域
        self:updateCharacterFieldTag(character, entity)
        -- 更新玩家的坐骑（玩家进入战斗的时候可能会下坐骑,所以这里放在外面更新）
        self:updateMount(character, info)
        -- 更新玩家速度 (从跟随变成未跟随时，需要更新速度，所以这里放在外面更新)
        self:updateSpeed(character, info)

        if entity:isBaseInfoUpdate() then
            self:updateAvatar(character, info)
            self:updateCharacterUpHead(character,info)
            entity:setBaseInfoUpdate(false)
        end
        -- 更新玩家名字颜色
        if app:getInst("DynastyMapModel"):isDynastyMap()  then
            self:updateCharacterDynastyShow(character, entity)
            -- 公会战中 显示其他队伍的人数
            if not isCharacterInMyTeam then
                local isEnemy = true
                local posX
                local leaderId = entity:getLeaderId()
                if leaderId == 0 then -- 表示该玩家是队长
                    posX = MathFloor(entity:getX())
                    leaderId = entity:getId()
                end
                -- 是否同一个公会
                local baseInfo = entity:getInfo()
                if baseInfo then
                    if baseInfo.guildID == UD:getGuildId() then
                        isEnemy = false
                    end
                end
                -- 更新
                app:sendMsg("DynastyMapController", "insertOtherTeamMember", leaderId, isEnemy, posX)
            end
        elseif UD.csGuildWarData:isCSGuildWarPrepareMap() then
            self:updateCharacterDynastyShow(character, entity)
        else
            executeFunc(colorFunc)
        end
    end
end

-- 更新玩家公会战中的显示
function FieldManager:updateCharacterDynastyShow(character, entity)
    if not character or not entity then return end

    local isEnemy = true
    -- 是否同一个公会
    local baseInfo = entity:getInfo()
    if baseInfo then
        if baseInfo.guildID == UD:getGuildId() then
            isEnemy = false
        end
    end

    character:setTitle("")
    if isEnemy then
        character:toDynastyEnemyColor()
        character:setGuildNameColor(Res.PlayerNameColors.DynastyEnemy)
    else
        character:toDynastyMyColor()
        character:setGuildNameColor(Res.PlayerNameColors.DynastyMy)
    end
end

-- 更新人物当前行为 Enums.behaviorType
-- 暂时默认优先显示顺序从前往后
function FieldManager:getShowBehavior(behavior)
    behavior = tonumber(behavior)
    if not behavior then return Enums.behaviorType.none end

    local bitFlag = 1
    for j = 1, 3 do
        if bit.band(behavior, bitFlag) >= 1 then 
            return bitFlag
        end
        bitFlag = bitFlag * 2
    end
    return Enums.behaviorType.none
end

function FieldManager:updateCharacterBehavior(character, entity)
    if not character or not entity then return end
    local behavior = self:getShowBehavior(entity:getBehavior())
    -- 公会战场 显示血量
    local bloodData = nil
    if behavior == Enums.behaviorType.none then
        if app:getInst("DynastyMapModel"):isDynastyMap() then
            bloodData = {}

            if UD.csGuildWarData:isCSGuildWarPrepareMap() then
                bloodData.type = 2
            else
                bloodData.type = 1
            end
            bloodData.enemy = true
            -- 是否同一个公会
            local baseInfo = entity:getInfo()
            if baseInfo then
                if baseInfo.guildID == UD:getGuildId() then
                    bloodData.enemy = false
                end
            end
            -- 血量
            local percent = entity:getHpPercent() * 100
            local hp = 1
            if percent >= 66 then
                hp = 3
            elseif percent >= 33 then
                hp = 2
            end
            bloodData.hp = hp
        elseif UD.csGuildWarData:isCSGuildWarPrepareMap() then
            bloodData = {}
            bloodData.type = 2
            bloodData.enemy = false
            -- 血量
            local percent = entity:getHpPercent() * 100
            local hp = 0
            if percent >= 67 then
                hp = 3
            elseif percent >= 34 then
                hp = 2
            elseif percent > 0 then
                hp = 1
            end
            bloodData.hp = hp
            -- 更新 血量
            local baseInfo = entity:getInfo()
            if baseInfo then
                if baseInfo.uid == UD.player.uid then
                    UD.csGuildWarData:setHp(hp)
                end
            end

        end
    end
    character:updateBehaviorNode(behavior, bloodData)
end

function FieldManager:updateMyBlood(character, entity)
    if not character or not entity then return end
    local percent = 100
    if app:getInst("DynastyMapModel"):isDynastyMap() then
        -- 只在公会战场景中显示当前血量
        percent = entity:getHpPercent() * 100
    end
 
    local desktopController = UIHandler:getDesktopController()
    if desktopController then
        local desktop = desktopController:getDesktop()
        if desktop then
            desktop:setLife(percent)
        end
    end     
end

function FieldManager:updateCharacterFieldTag(character, entity)
    if not character or not entity then return end
    local fieldTag = tonumber(entity:getFieldTag())
    local buff = nil
    
    if fieldTag == 1 then -- 回血区
        buff = "huixue"
    elseif fieldTag == 2 then -- 得分区
        buff = "defen"
    end
    character:playCharacterBuff(buff)
end

function FieldManager:playMyMainTaskEffect(buffName)
    if not self._myCharacter then return end
    self._myCharacter:playCharacterMainTaskEffect(buffName)
end

function FieldManager:canMyCharacterChangeMount()
    local canChange = false
    if not BattleManager:isWaitBattle()
      and not BattleManager:isBattle()
      and not StoryManager:isEnterStoryMode()
      and not DoEventHandler.isGather()
      and not self:isTransferring()
      and not app:sendMsg("PhotoController", "isInPhoto") then
        canChange = true
    else
        canChange = false
    end
    return canChange
end

function FieldManager:updateMount(character, userBaseInfo)
    if not userBaseInfo or not character then return end

    local canChange = true
    if not character:isMySelf() then
        if TeamModel:isWithTeam(character:getUid()) then
            canChange = self:canMyCharacterChangeMount()
        end

        if Config.ignoreOtherPlayerMount then
            canChange = false
        end

        if canChange then
            character:changeMount(userBaseInfo.mountID)
        end
    else
        canChange = self:canMyCharacterChangeMount()
        if canChange and userBaseInfo.mountID ~= nil
          and userBaseInfo.mountID ~= character:getMountId() then
            self:onChangeRide({mountId = userBaseInfo.mountID})
        end
    end
end

function FieldManager:updateSpeed(character, userBaseInfo)
    character:setCharacterSpeed(userBaseInfo.speed)
end

function FieldManager:updateAvatar(character, userBaseInfo)
    if not userBaseInfo or not character then return end
    character:changeAvatar(userBaseInfo)
end

function FieldManager:updateQueueCharacters()
    local charactersNum = self:getMapCharactersNum()
    local showPlayerNum = UD.setting:getShowPlayerNum()
    if charactersNum > showPlayerNum then
        -- 删除比玩家设置同屏显示人数更多的那部分avatar
        for uid, character in pairs(self._mapCharacters) do
            -- 首先，队友必须显示
            -- TODO: 其次，好友和同公会成员优先显示
            if character and not TeamModel:isInTeam(uid) then
                self:removeMapCharacterByUid(uid)
                if self:getMapCharactersNum() <= showPlayerNum then
                    break
                end
            end
        end
    end
    local queueEntityNum = #self._queueEntityInfos
    if queueEntityNum <= 0 then return end

    if BattleManager:isWaitBattle()
      or BattleManager:isBattle()
      or StoryManager:isEnterStoryMode() then
        return
    end
    charactersNum = self:getMapCharactersNum()
    local intervalTime = app:getTime() - self._lastUpdateQueueCharacterTime
    if intervalTime >= updateQueueCharacterInterval and charactersNum < showPlayerNum then
        self._lastUpdateQueueCharacterTime = app:getTime()
        local lastQueueEntityInfo = self:getLastQueueEntityInfo()
        if lastQueueEntityInfo then
            self:createOtherCharacter(lastQueueEntityInfo)
            self:deleteEntityInfoFromQueue(lastQueueEntityInfo.entityId)
        end
    end
end

function FieldManager:createOtherCharacter(entityInfo)
    local entityId = entityInfo.entityId
    local entity = self:getEntityById(entityId)
    if entity == nil then
        return
    end
    local parentLine = entityInfo.parentLine
    local posX = entity:getX()
    local character = self:getCharacterByUid(entityId)
    if character then
        character:rayCastFoothold(posX)
        if entity:isFaceToLeft() then
            character:faceToLeft()
        else
            character:faceToRight()
        end
        return
    end
    local userInfo = entity:getInfo()
    -- 获取玩家基础显示信息
    if not cc.isAlive(userInfo) then
        return
    end

    local params = userInfo:clone()
    params.inBattle = false
    params.isUseAsyncLoad = true
    character = Character.new(params)
    character:setNameNode(NodeFactory:createHeadName())
    character:setUid(entityId)
    character:setLevel(userInfo.lv)
    -- character:showLocation(cc.p(posX,display.height * 0.5))
    -- character:rayCastFoothold(posX)
    -- character:showLocationX(posX)
    self:updateCharacterUpHead(character,userInfo)
    self:updateCharacterBehavior(character, entity)
    self:updateCharacterFieldTag(character, entity)

    character:addDefStyleAction()

    if DEBUG == -1 then
        character:setName("")
        character:setTitle("")
    end

    character:toNormalColor()

    character:setOriginalLine(character:getRandomLine())
    if TeamModel:isWithTeam(entityId) then
        character:setLine(character.LINE_2)
    else
        character:setLine(parentLine or character:getOriginalLine())
    end
    character:showLocationX(posX) -- 设置落脚点要放在setline后面

    MapManager:addCharacterToMap(character)
    -- character:rayCastFoothold(posX)
    local mountId = tonumber(userInfo.mountID)
    if Config.ignoreOtherPlayerMount then
        mountId = 0
    end
    character:getOnRide(mountId)
    character:setChangeAvatarCallback(function(uid)
        app:dispatchCustomEvent("EVENT_REFRESH_PLAYER_HEAD",{uid = uid})
    end)
    app:dispatchCustomEvent("EVENT_REFRESH_PLAYER_HEAD",{uid = entityId})
    self:addMapCharacter(character)
    if self:isHidingCharacters() or self._hidingNotTeamCharacter then
        character:hideSelf()
    end
    character:setAllOpacity(0)
    character:excuteAction(cc.FadeIn:create(0.5), 255)

    -- 单独更新一次随从信息（其实这里可以直接调用 updateSingleCharacter 来全部更新，但是前面已经有好几个更新接口单独调用了，这里就先不重复调用了）
    self:updateCharacterFollowMercenary(userInfo.partners, character)
end

function FieldManager:buildLionHornCharacters(playerInfos)
    self._myCharacter:faceToRight()
    local uidList = {}
    for _, playerInfo in ipairs(playerInfos) do
        local baseInfo = playerInfo:getInfo()
        local specialUid = "lionHorn_"..baseInfo.uid
        table.insert(uidList, specialUid)
        if baseInfo.uid ~= app.session.uid and self._lionHornCharacters[specialUid] == nil then
            baseInfo.isUseAsyncLoad = false
            local character = Character.new(baseInfo)

            character:setNameNode(NodeFactory:createHeadName())
            character:setUid(specialUid)
            character:setName(baseInfo.name)
            self:updateCharacterUpHead(character, baseInfo)

            -- character:setMySelf(false)
            character:setLine(character.LINE_2)
            -- character:setLinesData(MapManager:getLinesData())

            -- 将人物挂接在地图的某个line（行走层）上
            MapManager:getMap():addCharacter(character,1)
            character:setDefaultSpeed(0)
            character:setSpeed(0)
            -- character:rayCastFoothold(playerInfo:getPos())
            character:showLocationX(playerInfo:getPos())
            character:faceToRight()
            character:standby()

            self:addMapCharacter(character)
            self._lionHornCharacters[specialUid] = character
        end
    end
    local removeUidList = {}
    for uid, character in pairs(self._lionHornCharacters) do
        local needRemove = true
        for _, uidExisted in ipairs(uidList) do
            if uid == uidExisted then
                needRemove = false
                break
            end
        end
        if needRemove then
            table.insert(removeUidList, uid)
        end
    end
    for _, uid in ipairs(removeUidList) do
        self._lionHornCharacters[uid] = nil
        self:removeMapCharacterByUid(uid)
    end
end

function FieldManager:onParseMapUpdate(msg)
    -- 更新视野范围内所有玩家enitity
    self._mapUpdate:read(msg)
   -- dump(msg, "===> S2C_MapUpdate", 10)

   if DEBUG > 0 then
        app:dispatchCustomEvent("temp_pos_desktop_refresh")
    end

    -- 组装所有玩家entity的队伍信息
    TeamManager:updateTeamEntities()

    -- 更新所有玩家的avatar
    self:updateMapCharacters()
end

-- function FieldManager:onParseMapUsersUpdateResponse(msg,debug)
--     self:updateMapCharacters()
-- end

function FieldManager:updateNearbyUser()
    self._nearbyUsers = {}
    local ox = self:getSelfEntity():getX()
    local tEntities = {}
    for _, entity in pairs(self:getOtherEntities()) do
        table.insert(tEntities, entity)
    end
    table.sort(tEntities, function(a,b) return MathAbs(a:getX() - ox) < MathAbs(b:getX() - ox) end)
    local num = 0
    for _,entity in ipairs(tEntities) do
        if entity:getInfo() then
            self._nearbyUsers[entity:getInfo().uid] = entity:getInfo()
            num = num + 1
        end
        if num >= 10 then break end
    end
end

function FieldManager:getNearbyUserNotInTeam()
    self:updateNearbyUser()
    return self._nearbyUsers
end

function FieldManager:createTheatreChatacters(myMembers, enemyMembers, posAry)
    local characters = {}
    for i,member in ipairs(myMembers) do
        if member:isMe() then
            self._myCharacter:changeMount(0)
            self._myCharacter:faceToRight()
            self._myCharacter:setUserBaseInfo(member:getAvatarParams())
            self._myCharacter:showLocationX(posAry[i])
            characters[#characters + 1] = self._myCharacter
        else
            local info = member:getAvatarParams()
            local character = Character.new(info)
            character:setNameNode(NodeFactory:createHeadName())
            character:setUid(info.uid)
            character:setName(info.name)
            character:faceToRight()
            character:setLine(character.LINE_2)
            -- character:setLinesData(MapManager:getLinesData())

            character:showLocationX(posAry[i])

            -- 将人物挂接在地图的某个line（行走层）上
            MapManager:getMap():addCharacter(character,1)
            self:addMapCharacter(character)

            characters[#characters + 1] = character
        end
    end

    self._theatreMyChatacters = characters

    characters = {}
    for i,member in ipairs(enemyMembers) do
        local info = member:getAvatarParams()
        local character = Character.new(info)
        character:setNameNode(NodeFactory:createHeadName())
        character:setUid(info.uid)
        character:setName(info.name)
        character:faceToLeft()
        character:setLine(character.LINE_2)
        -- character:setLinesData(MapManager:getLinesData())

        character:showLocationX(posAry[i + 5])

        -- 将人物挂接在地图的某个line（行走层）上
        MapManager:getMap():addCharacter(character,1)
        self:addMapCharacter(character)

        characters[#characters + 1] = character
    end

    self._theatreEnemyChatacters = characters

    return self._theatreMyChatacters, self._theatreEnemyChatacters
end

-- 初始化星空谜棋角色
function FieldManager:createChessCharacter(myInfo, enemyInfo)
    self._myCharacter:changeMount(0)
    self._myCharacter:setUserBaseInfo(myInfo)

    -- init enemy character
    local character = Character.new(enemyInfo)
    self._chessCharacter = character
    character:setNameNode(NodeFactory:createHeadName())
    character:setUid(enemyInfo.uid)
    character:setName(enemyInfo.name)
    character:faceToRight()
    character:setLine(character.LINE_2)
    -- character:setLinesData(MapManager:getLinesData())
    character:setMapPositionError(0)

    character:showLocation(0,display.cy)

    -- 将人物挂接在地图的某个line（行走层）上
    MapManager:getMap():addCharacter(character,1)

    self:addMapCharacter(character)

    return self._myCharacter, self._chessCharacter
end

function FieldManager:updateMyCharacterName()
    if self._myCharacter then
        self._myCharacter:setName(UD:getNickName())
    end
end

-- 玩家当前状态，用于同步给其他队员
-- 0-正常 1-暂离 2-战斗 3-移动 4-巡逻
function FieldManager:getMyCharacterActionState()
    local actionState = 0
    if BattleManager:isInBattle() then
        actionState = 2
    else
        if cc.isAlive(self._myCharacter) then
            if self._myCharacter:isAutoPatrol() then
                actionState = 4
            elseif self._myCharacter:isMove() then
                actionState = 3
            end
        end
    end
    return actionState
end

function FieldManager:createMyCharacter(transX, baseInfo)
    local isFaceToRight = true
    if not baseInfo then
        local selfEntity = self:getSelfEntity()
        if selfEntity:getInfo() then
            baseInfo = selfEntity:getInfo():clone()
            isFaceToRight = selfEntity:isFaceToRight()
        else
            baseInfo = UD:getAvatarParams()
        end
    end
    baseInfo.isUseAsyncLoad = false

    local character = Character.new(baseInfo, true)
    self._myCharacter = character
    character:setNameNode(NodeFactory:createHeadName())
--    character:setBubble(NodeFactory:createBubble())
    character:setUid(baseInfo.uid)
    character:setName(baseInfo.name)
    character:setTitle(UD:getTitleName(baseInfo.titleID))
    character:setGuildName(baseInfo.guildName)

    character:getOnRide(baseInfo.mountID)
    character:toNormalColor()

    character:addDefStyleAction()

    -- 巡逻切换回调
    character:onSwitchAutoPatrol(function(auto)
        if auto then
            app:sendMsg("TeamModel", "reqPostPlayerState", 4)
        else
            UIHandler:postDesktopState()
        end
    end)

    if isFaceToRight then
        character:faceToRight()
    else
        character:faceToLeft()
    end

    character:setLine(character.LINE_2)

    local sx = transX and transX or 400
    local sy = display.height * 0.5
    character:showLocationX(sx)

    -- 将人物挂接在地图的某个line（行走层）上
    MapManager:getMap():addCharacter(character,1)

    self:addMapCharacter(character)


    character:standby()

    -- character:setLinesData(MapManager:getLinesData())

    -- character:rayCastFoothold(sx)

    MapManager:setFocusCharacterForInit({character = character})

    self._screenlayer = cc.Layer:create()
    MapManager:getWorld():addChild(self._screenlayer)
    MapManager:getMap():initCustomNode(self._screenlayer)
    MapManager:getMap():setScreenLayer(self._screenlayer)

    self:setOwnerX(sx)

    self:updateSelfTaskFollowMercenary(baseInfo)

    character:setSendNextEventsCall(function()
        if not StoryManager:isEnterStoryMode() and self._myCharacter:isAutoWayFinding() then
            app:dispatchCustomEvent("EVENT_NEXT_EVENTS")
            if self:isArriveTarget() then
                self:setTargetInfo(nil)
                app:dispatchCustomEvent("EVENT_STOP_TRACKING")
                app:dispatchCustomEvent("EVENT_NPC_TRACK",{start = false})
            end
        end
    end)

    character:setActionChangedCallback(function()
        self:resetTimer()
        self:refreshMyCharacterPositionToServer()

        -- 开始移动的时候设置标记，每隔一段时间向服务器上报
        self._characterIsMoving = false
        local status = self:getCharacterStatus()
        if status == Enums.status.run then
            self._characterIsMoving = true
            self._lastMoveSyncPosTime = app:getTime()
        end
    end)

    character:setDirectionChangedCall(function()
        self:resetTimer()
        self:refreshMyCharacterPositionToServer()
    end)

    character:setChangeAvatarCallback(function(uid)
        app:dispatchCustomEvent("EVENT_REFRESH_PLAYER_HEAD",{uid = uid})
    end)

    character:setGetOffRideCallback(function()
        TeamManager:autoTeamMemberGetOffRide()
    end)

    app:dispatchCustomEvent("EVENT_REFRESH_PLAYER", baseInfo)
end

function FieldManager:buildPuppetCharacter(dir, x, inBattle)
    if not self._myCharacter then return end
    if self:getPuppetCharacter() then return end

    local params
    if self:getSelfBaseInfo() then
        params = clone(self:getSelfBaseInfo())
    else
        params = UD:getAvatarParams()
    end
    params.isUseAsyncLoad = false
    params.inBattle = inBattle
    local puppetCharacter = Character.new(params, true)
--    puppetCharacter:setBubble(NodeFactory:createBubble())
    puppetCharacter:setUid(UD:getUid())
    puppetCharacter:setLine(puppetCharacter.LINE_2)
    -- puppetCharacter:setLinesData(MapManager:getLinesData())
    -- puppetCharacter:setMySelf(true)

    -- local pos = cc.p(self._myCharacter:getPosition())
    -- puppetCharacter:showLocation(pos)
    if not x then
        x = self._myCharacter:getPosition()
    end
    puppetCharacter:showLocationX(x)
    -- puppetCharacter:rayCastFoothold(x)

    MapManager:getMap():addCharacter(puppetCharacter,1)

    if dir == "l" then
        puppetCharacter:faceToLeft()
    else
        puppetCharacter:faceToRight()
    end

    puppetCharacter:standby()

    -- puppetCharacter:rayCastFoothold(x,0)

    MapManager:setFocusCharacterForInit({character = puppetCharacter})

    puppetCharacter:setGetOffRideCallback(function()
        TeamManager:autoTeamMemberGetOffRide()
    end)

    self:setPuppetCharacter(puppetCharacter)
    -- self:stopShowMyCharacterUpHead(true)
end

function FieldManager:deletePuppetCharacter()
    if self:getPuppetCharacter() then
        MapManager:getMap():removeCharacter(self:getPuppetCharacter())
        MapManager:setFocusCharacter({character = self._myCharacter})
        self:setPuppetCharacter(nil)
    end
end

function FieldManager:reportMyCharacterMovingToServer()
    if not self:isStopSendPosition() and not DoEventHandler.isGather() and not TeamModel:isWithTeam() then
        app.session:request("pb_map.C2S_OnMoving", {})
    end
end

function FieldManager:refreshMyCharacterPositionToServer(isStop)
    self:reportMyCharacterPosToServer(isStop)
    -- 添加一个 进入游戏 首次移动 埋点事件
    -- if not self._isFirsttMoveEventPop and app:isBattleGuideComp() and self:getCharacterStatus() == Enums.status.run then
    --     self._isFirsttMoveEventPop = true
    --     EM:notify("OnFirstMoveEvent")
    -- end
    if DEBUG > 0 then
        app:dispatchCustomEvent("temp_pos_desktop_refresh")
    end
end

function FieldManager:reportMyCharacterPosToServer(isStop)
    if not self:isStopSendPosition() and not DoEventHandler.isGather() and not TeamModel:isWithTeam() then
        local msg = self:getCharacterUpdateMsg(isStop)
        if msg.status == Enums.status.idle and self.lastReportPosStatus == Enums.status.idle then
            return
        end
--        print("======> ", app:getServerTime())
--        dump(msg, "pb_map.C2S_UpdatePos", 10)
        self.lastReportPosStatus = msg.status
        app.session:notify("pb_map.C2S_UpdatePos",msg)
    end
end

function FieldManager:setStopSendPosition(isStop)
    self._stopSendPosition = isStop
end

function FieldManager:isStopSendPosition()
    return self._stopSendPosition
end

function FieldManager:adjustSelfToFixedPosition(destX)
    if not self._myCharacter then return end
    self._myCharacter:showLocationX(destX)
    self._myCharacter:setTargetX(destX)
    MapManager:initCamera()
    MapManager:resetMapFocus()
end

local triggeredNewerBattleGuide = false -- 是否触发过新手战

function FieldManager:setCharacterX(posX)
    if not app:isBattleGuideComp() then
        local posTriggerBattle = app:sendMsg("NewerbattleguideController", "getMapPositionTriggerBattle")
        if posTriggerBattle and posX >= posTriggerBattle and not triggeredNewerBattleGuide then
            triggeredNewerBattleGuide = true
            app:sendMsg( "NewerbattleguideController", "triggerNewerBattle" )
        end
    end
    self._chaPosX = posX
end

function FieldManager:getCharacterX()
    local pos = self._chaPosX
    if not cc.isDead(self._myCharacter) then
        pos = NodeGetPositionXFunc(self._myCharacter)
    end
    return pos
end

function FieldManager:setCharacterY(posY)
    self._chaPosY = posY
end

function FieldManager:getCharacterY()
    return self._chaPosY
end

function FieldManager:getCharacterDirection()
    local direction = Enums.FaceTo.right
    local character = self._myCharacter
    if not character then return direction end

    if character:isFaceToRight() then
        direction = Enums.FaceTo.right
    else
        direction = Enums.FaceTo.left
    end

    return direction
end

function FieldManager:getCharacterStatus()
    local status = Enums.status.idle
    local character = self._myCharacter
    if character then
        status = character:isMove()
            and Enums.status.run
            or Enums.status.idle
    end
    return status
end

function FieldManager:getCharacterUpdateX()
    local curX = self:getCharacterX()

    if self._lastCharacterX ~= curX then
        self._lastCharacterX = curX
        return true,curX
    else
        return false,curX
    end
end

function FieldManager:getCharacterUpdateMsg(isStop)
    local _ ,curX = self:getCharacterUpdateX()
    if not self._notifyPackect then
        self._notifyPackect = {}
    end

    self._notifyPackect.faceTo = self:getCharacterDirection()
    self._notifyPackect.posX = curX
    self._notifyPackect.status = self:getCharacterStatus()
    if isStop then
        self._notifyPackect.status = Enums.status.idle
    end
    self._notifyPackect.mapId = MapManager:getMapId()
    return self._notifyPackect
end

function FieldManager:addMapCharacter(character)
    if not character then return end
    if not self:getCharacterByUid(character:getUid()) then
        self._mapCharacters[character:getUid()] = character
    end
end

function FieldManager:removeMapCharacterByUid(uid)
    local character = self._mapCharacters[uid]
    if character and uid ~= UD:getUid() then
        self._mapCharacters[uid] = nil
        self:removeCharacterMercenary(character)
        self:dispatchEvent({name = "map_delete_character",character = character})
    end
end

function FieldManager:getMapCharacters()
    return self._mapCharacters
end

function FieldManager:getFollowCharacters()
    local characters = {}
    for _,member in ipairs(TeamModel:getMembers()) do
        local character = self:getCharacterByUid(member.userBaseInfo.uid)
        if character then
            characters[#characters + 1] = character
        end
    end
    for _,robot in ipairs(TeamModel:getRobots()) do
        local uid = robot:getUid()
        local character = self:getCharacterByUid(uid)
        if character then
            characters[#characters + 1] = character
        end
    end

    return characters
end

function FieldManager:setFollowCharactersOpacity(opacity)
    local characters = self:getFollowCharacters()
    for _,character in pairs(characters) do
        character:setAllOpacity(opacity)
    end
end

function FieldManager:setFollowCharactersBattleMark(isShow)
    for _,member in ipairs(TeamModel:getMembers()) do
        local character = self:getCharacterByUid(member.userBaseInfo.uid)
        if character then
            if isShow then
                character:showBattleMark()
            else
                character:hideBattleMark()
            end
        end
    end
    for _,robot in ipairs(TeamModel:getRobots()) do
        local character = self:getCharacterByUid(robot.id)
        if character then
            if isShow then
                character:showBattleMark()
            else
                character:hideBattleMark()
            end
        end
    end
end

function FieldManager:getMapCharactersNum()
    return table.nums(self._mapCharacters)
end

function FieldManager:getCharacterByUid(uid)
    return self._mapCharacters[uid]
end

-- function FieldManager:getLeaderCharacter()
--     for _,character in pairs(self._mapCharacters) do
--         if character then
--             if TeamModel:isLeader(character:getUid()) then
--                 return character
--             end
--         end
--     end
--     return nil
-- end

function FieldManager:allCharacterVisibility(visible,isFade)
    for _,character in pairs(self._mapCharacters) do
        local action, opacity
        if visible then
            if isFade and not character:isMySelf() then
                opacity = 255
                action = cc.Sequence:create(cc.CallFunc:create(function()
                    character:showSelf()
                end),cc.FadeTo:create(0.5,255))
            else
                character:showSelf()
            end
        else
            if isFade and not character:isMySelf() then
                opacity = 0
                action = cc.Sequence:create(cc.FadeTo:create(0.5,0),cc.CallFunc:create(function()
                    character:hideSelf()
                end))
            else
                character:hideSelf()
            end
        end
        if action then
            character:excuteStopAllActions()
            character:excuteAction(action, opacity)
        end
    end
end

function FieldManager:exceptSelfCharactersVisibility(visible,isFade)
    for _,character in pairs(self._mapCharacters) do
        local action, opacity
        if visible then
            if isFade and not character:isMySelf() then
                opacity = 255
                action = cc.Sequence:create(cc.CallFunc:create(function()
                    character:showSelf()
                end),cc.FadeTo:create(0.5,255))
            elseif not character:isMySelf() then
                character:showSelf()
                character:setAllOpacity(255)
            end
        else
            if isFade and not character:isMySelf() then
                opacity = 0
                action = cc.Sequence:create(cc.FadeTo:create(0.5,0),cc.CallFunc:create(function()
                    if not tolua.isnull(character) then
                        character:hideSelf()
                    end
                end))
            elseif not character:isMySelf() then
                character:hideSelf()
            end
        end
        if action then
            character:excuteStopAllActions()
            character:excuteAction(action, opacity)
        end
    end
end

function FieldManager:fadeCharacter(visible,isFade,character,time)
    if not character then return end
    local fadeTime = time or 0.5
    local action, opacity
    if visible then
        if isFade then
            opacity = 255
            action = cc.Sequence:create(cc.FadeTo:create(fadeTime,255),cc.CallFunc:create(function()
                if not tolua.isnull(character) then
                    character:showSelf()
                end
            end))
            character:excuteStopAllActions()
            character:excuteAction(action, opacity)
        else
            character:showSelf()
        end

    else
        if isFade then
            opacity = 0
            action = cc.Sequence:create(cc.FadeTo:create(fadeTime,0),cc.CallFunc:create(function()
                if not tolua.isnull(character) then
                    character:hideSelf()
                end
            end))
            character:excuteStopAllActions()
            character:excuteAction(action, opacity)
        else
            character:hideSelf()
        end
    end
end

-- 显示 或 隐藏 人物名字节点（与设置界面的 头顶信息 同步）
function FieldManager:updateAllCharactersUpHead(isShow)
    FieldManager._hideAllCharacterUpHead = not isShow -- 本地存储 是否显示人物头顶信息

    for _,character in pairs(self._mapCharacters) do
        if character and NodeIsVisibleFunc(character) then
            character:updateUpHead()
        end
    end
end

function FieldManager:fadeInAllCharacters(time)
    local fadeTime = time or 0
    for _,character in pairs(self._mapCharacters) do
        if character then
            local action = cc.FadeIn:create(fadeTime)
            character:excuteStopAllActions()
            character:excuteAction(action, 255)
        end
    end
end

function FieldManager:fadeOutAllCharacters(time)
    local fadeTime = time or 0
    for _,character in pairs(self._mapCharacters) do
        if character then
            local action = cc.FadeOut:create(fadeTime)
            character:excuteStopAllActions()
            character:excuteAction(action, 0)
        end
    end
end

function FieldManager:fadeOutAllCharactersExceptTeam(time)
    local fadeTime = time or 0
    for _,character in pairs(self._mapCharacters) do
        if character and not character:isMySelf() and not TeamModel:isWithTeam(character:getUid()) then
            local action = cc.FadeOut:create(fadeTime)
            character:excuteStopAllActions()
            character:excuteAction(action, 0)
        end
    end
end

function FieldManager:hideAllIMBubble()
    for _,character in pairs(self._mapCharacters) do
        if character then
            character:hideIMBubble()
        end
    end
end

function FieldManager:stopShowAllIMBubble(isStop)
    for _,character in pairs(self._mapCharacters) do
        if character then
            character:stopShowIMBubble(isStop)
        end
    end
end

function FieldManager:hideExceptMainCharacter()
    for _,character in pairs(self._mapCharacters) do
        if character ~= self._myCharacter then
            character:hideSelf()
        end
    end
end

function FieldManager:updateMyCharacter()
    local character = self._myCharacter
    if character and self:getPuppetCharacter() then
        if NodeIsVisibleFunc(character) then
            character:allVisibility(false)
            NodeSetVisibleFunc(character,false)
        end
    end
end

function FieldManager:forceShowMainCharacter()
    local character = self._myCharacter
    if character then
        character:setEventVisibility(false)
        character:showSelf()
        character:hideBattleMark()
    end
end

function FieldManager:setMainCharacterOpacity(opacity)
    local puppetCharacter = self:getPuppetCharacter()
    if puppetCharacter then
        puppetCharacter:setOpacity(opacity)
    elseif self._myCharacter then
        self._myCharacter:setOpacity(opacity)
    end
end

function FieldManager:updateMapUsersVisibility()
    if BattleManager:isBattle() then
        self:hideExceptTeamCharacter()
    elseif self:isShowUiOperate() then
        self:showTeamCharacterAndHideOther()
    end
    self:updateMyCharacter()
end

function FieldManager:showTeamCharacterAndHideOther()
    for _,character in pairs(self._mapCharacters) do
        if TeamModel:isInTeam(character:getUid()) or (character == self._myCharacter) then
            character:showSelf()
        else
            character:hideSelf()
        end
    end
end

function FieldManager:showAllCharacter()
    for _,character in pairs(self._mapCharacters) do
        character:showSelf()
    end
end

function FieldManager:hideExceptTeamCharacter()
    for _,character in pairs(self._mapCharacters) do
        if not TeamModel:isInTeam(character:getUid()) and character ~= self._myCharacter then
            character:hideSelf()
        end
    end
end

-- 新的接口 隐藏 非队伍内的玩家， 同时也移除他们的随从（等放开显示的时候，会再重新添加他们的随从）
function FieldManager:hideNotTeamCharacter()
    for _,character in pairs(self._mapCharacters) do
        if not TeamModel:isInTeam(character:getUid()) and character ~= self._myCharacter then
            character:hideSelf()
            self:removeCharacterMercenary(character)
        end
    end
end

-- 更新一次所有玩家的随从
function FieldManager:updateAllCharacterMercenary()
    -- 更新其他玩家
    for _, entity in pairs(self:getOtherEntities()) do
        local entityId = entity:getId()
        local character = self:getCharacterByUid(entityId)
        local info = entity:getInfo()
        if info then
            -- 更新随从的avatar
            self:updateCharacterFollowMercenary(info.partners, character)
        end
    end

    -- 更新自己
    local selfEntity = self:getSelfEntity()
    local info = selfEntity:getInfo()
    if info and self._myCharacter then
        -- 更新随从的avatar
        self:updateCharacterFollowMercenary(info.partners, self._myCharacter)
    end
end

local CharacterUpdateFrame = Character.updateFrame

function FieldManager:updateCharacters(dt)
    for _,character in pairs(self._mapCharacters) do
        CharacterUpdateFrame(character,dt)
    end
    local puppetCharacter = self:getPuppetCharacter()
    if puppetCharacter then
        CharacterUpdateFrame(puppetCharacter,dt)
    end
end

function FieldManager:characterVisibility(visible)
    if visible then
        self:allCharacterVisibility(visible)
        if self:getPuppetCharacter() then
            self:getPuppetCharacter():showSelf()
        elseif self._myCharacter then
            self._myCharacter:showSelf()
        end
    else
        self:allCharacterVisibility(visible)

        if self:getPuppetCharacter() then
            self:getPuppetCharacter():hideSelf()
        end

        if self._myCharacter then
            self._myCharacter:hideSelf()
        end
    end
end

function FieldManager:startHideCharacters(isFade)
    if not self._myCharacter then return end

    self:setHidingCharacters(true)
    if BattleManager:isBattle() then
        self:exceptSelfCharactersVisibility(false,isFade)
        if self:getPuppetCharacter() then
            if not self:isShowMainCharacterInBattle() then
                self:fadeCharacter(false,isFade,self:getPuppetCharacter())
                self:fadeCharacter(false,isFade,self._myCharacter)
            end
        else
            if self:isShowMainCharacterInBattle() then
                self:fadeCharacter(true,isFade,self._myCharacter)
            else
                self:fadeCharacter(false,isFade,self._myCharacter)
            end
        end
    else
        if self:getPuppetCharacter() then
            self:exceptSelfCharactersVisibility(false,isFade)
            self:getPuppetCharacter():showSelf()
            self._myCharacter:hideSelf()
        else
            self:exceptSelfCharactersVisibility(false,isFade)
            if StoryManager:isEnterStoryMode() or DoEventHandler.isOpenUI() then
                self._myCharacter:showSelf()
            end
        end
    end
end

function FieldManager:stopHideCharacters(isFade)
    self:setHidingCharacters(false)
    self:allCharacterVisibility(true,isFade)
end

function FieldManager:hideMyCharacter()
    self._myCharacter:excuteStopAllActions()
    self._myCharacter:setOpacity(255)
    self._myCharacter:hideSelf()
end
function FieldManager:showMyCharacter()
    self._myCharacter:showSelf()
end

function FieldManager:showMainCharacterInBattle(show)
    self._showMainCharacterInBattle = show
end

function FieldManager:isShowMainCharacterInBattle()
    return self._showMainCharacterInBattle
end

function FieldManager:setPuppetCharacter(character)
    self._puppetCharacter = character
end

function FieldManager:getPuppetCharacter()
    return self._puppetCharacter
end

function FieldManager:stopShowMyCharacterUpHead(isStop)
    if self._myCharacter then
        self._myCharacter:stopShowUpHead(isStop)
    end
    if self:getPuppetCharacter() then
        self:getPuppetCharacter():stopShowUpHead(isStop)
    end
end

function FieldManager:stopShowAllCharactersUpHead(isStop)
    for _,character in pairs(self._mapCharacters) do
        if character then
            character:stopShowUpHead(isStop)
        end
    end
end

function FieldManager:updateCharacterUpHead(character, userBaseInfo)
    if not character or not userBaseInfo then return end
    -- if ToNumber(user.uid) == ToNumber(UD:getUid()) then return end
    if self:isStopEvent() then return end
    if DoEventHandler.isOpenUI() then return end
    character:setName(userBaseInfo.name)

    character:setTitle(UD:getTitleName(userBaseInfo.titleID))

    character:setGuildName(userBaseInfo.guildName)
end

function FieldManager:onPlayHearthStone(params)
    local character = self._myCharacter
    if character then
        character:playAni("lushi",0)
    end
    character = self:getPuppetCharacter()
    if character then
        character:playAni("lushi",0)
    end
end

function FieldManager:onChangeRide(params)
    -- self:updateMountSpeed()
    local mountId = params.mountId
    local character = self._myCharacter
    if character then
        if mountId then
            if character:isGetOnRide() then
                character:getOffRide()
            end
            character:getOnRide(mountId)
        else
            character:getOffRide()
        end
    end
end

function FieldManager:onGetOffRide()
    local character = self._myCharacter
    if character then
        character:getOffRide()
    end
    character = self:getPuppetCharacter()
    if character then
        character:getOffRide()
    end
end

function FieldManager:autoGetOnRide()
    local character = self._myCharacter
    if character then
        character:autoGetOnRide()
    end
end

function FieldManager:onChangeEquip(uid, equip, op)
    local character = self._myCharacter
    if character then
        -- 穿装备都播放特效
        if op == "insert" then
            character:playEquipAnimation(equip.location)
        end
    end
end

function FieldManager:onChangeEquipGrid(equipGrid, preFashionId, hasAvatarChange, hasHiddenChange)
    local character = self._myCharacter
    if character and (hasAvatarChange or hasHiddenChange) then
        -- 外显变化更新形象
        local params = UD:getAvatarParams()
        local hiddenFlag = equipGrid:getHidden()
        if preFashionId > 0 then
            local isOff = true
            if hasHiddenChange then
                isOff = hiddenFlag
            end
            character:changeEquip( params, preFashionId, isOff)
        end
        local fashionId = equipGrid:getAvatarFashionId()
        if fashionId > 0 then
            character:changeEquip(params, fashionId, hiddenFlag)
        end
    end
end

function FieldManager:onLevelUpAnimation()
    local character = self._myCharacter
    if not cc.isDead(character) then
        local delayAction = cc.Sequence:create(cc.DelayTime:create(0.3),cc.CallFunc:create(function()
            if not cc.isDead(character) then
                character:playLevelUpAnimation()
            end
        end))
        character:runAction(delayAction)
    end
end

function FieldManager:characterStopMove(immediately)
    local character = self._myCharacter
    if character then
        character:stopMove(immediately)
    end
    character = self:getPuppetCharacter()
    if character then
        character:stopMove(immediately)
    end
    --app:dispatchCustomEvent("EVENT_CHARACTER_STOP_MOVE")
end

function FieldManager:charactersPrepareBattle()
    local character = self._myCharacter
    if character then
        character:prepareBattle()
    end
    character = self:getPuppetCharacter()
    if character then
        character:prepareBattle()
    end
    for _,character in pairs(TeamManager:getTeamCharacters()) do
        character:prepareBattle()
    end
end

function FieldManager:characterForceStandby()
    local character = self._myCharacter
    if character then
        character:forceStandby()
    end
    character = self:getPuppetCharacter()
    if character then
        character:forceStandby()
    end
end

function FieldManager:getMyCharacterBoundingBox()
    if self._myCharacter then
        return self._myCharacter:getBoundingBox()
    end
    return nil
end

function FieldManager:isTouchMyCharacterXAxis(touchx,event)
    local cx = self:getCharacterX()
    local boundingBox = self:getMyCharacterBoundingBox()
    if boundingBox then
        if touchx >= cx + boundingBox.x + boundingBox.width / 3
            and touchx <= cx + boundingBox.x + boundingBox.width / 3 * 2 then
            if event ~= 'ended' then
                return true
            end
        end
    end
    return false
end

function FieldManager:isMyCharacterCanMove()
    if DoEventHandler.isGather() then
        return false
    end
    return true
end

function FieldManager:saveAutoWayParams(params)
    self._autoWayParams = params
end

function FieldManager:getAutoWayParams()
    return self._autoWayParams
end

function FieldManager:updateAutoWayParams(task)
    if not task then return end
    if self._autoWayParams and not task:isTaken() then
        if ToNumber(self._autoWayParams.trackTaskId) == ToNumber(task:getId()) then

            self:clearAutoWayFindingParams()

            -- 任务完成之后 不再对该任务进行巡逻
            if self._myCharacter then
                self._myCharacter:setAutoPatrol(false)
                self._myCharacter:setTargetX(self:getCharacterX())
            end

            -- 感觉下面这两个也是要清理的
            -- TaskManager:setCurrentTrackTaskId(nil)
            -- DoEventHandler.setTracking(false)
        end
    end
end

function FieldManager:getCharacterStartPos(transNpcId,mapId)
    local defaultX = 390
    local sx = 0
    local sy = display.height * 0.5
    local tTransNpcId = transNpcId
    local npcConfig = GD:queryMapNpc(transNpcId)
    if transNpcId and npcConfig and npcConfig.coordinate then
        sx = ToNumber(npcConfig.coordinate)
        tTransNpcId = transNpcId
    else
        local mapConfig = GD:queryMapById(mapId)
        if mapConfig and mapConfig.Bornat then
            transNpcId = ToNumber(mapConfig.Bornat)
            --local npc = getTransNpc(transNpcId)
            if npcConfig and npcConfig.coordinate then
                sx = ToNumber(npcConfig.coordinate)
            else
                sx = defaultX
            end
            tTransNpcId = transNpcId
        else
            sx = defaultX
        end
    end

    return sx,sy,tTransNpcId
end

function FieldManager:isStopEvent()
    if StoryManager:isEnterStoryMode()
        or BattleManager:isWaitBattle()
        or BattleManager:isBattle()
        or StoryManager:isExitStoryModeDelay() then
        return true
    end
    return false
end

function FieldManager:stopTouch(stop)
    self._stopTouch = stop
end

-- function FieldManager:isStopTouch()
--     return self._stopTouch
-- end

function FieldManager:isStopTouches()
    if not self._updateFrame then
        return true
    end

    if self._stopTouch then
        return true
    end

    if self:isStopTeamTouch() then
        return true
    end

    if DoEventHandler.isGather() then
        return true
    end

    return false
end

function FieldManager:setHidingCharacters(hiding)
    self._hidingCharacters = hiding
end

function FieldManager:isHidingCharacters()
    return self._hidingCharacters
end

-- 隐藏 或 显示 非队伍内玩家 
function FieldManager:setHidingNotTeamCharacter(hiding)
    self._hidingNotTeamCharacter = hiding -- (独立于 self._hidingCharacters , 这个是旧的，暂时先不管)
    if hiding then
        self:hideNotTeamCharacter()
    else
        self:showAllCharacter()
        self:updateAllCharacterMercenary() -- 更新所有玩家的随从
    end
end

function FieldManager:isTouchMyCharacter(touchPoint)
    local character = self._myCharacter
    if character then
        if character:containWorldPoint(touchPoint.x,touchPoint.y) then
            return true
        end
    end
    return false
end

function FieldManager:isTouchCharacter(touchPoint,event)
    if self._myCharacter then
        if self._myCharacter:isMove() then
            return false
        end
    end

    for _,character in pairs(self._mapCharacters) do
        if character:getUid() ~= UD:getUid() and character:isVisible() then
            if event == "began" and character:containWorldPoint(touchPoint.x,touchPoint.y) then
                UIHandler:showHeadMenu({online=true, attr=character:getUserBaseInfo(), pos=touchPoint})
                return true
            end
        end
    end

    return false
end

function FieldManager:isTouchChessCharacter(posX, posY)
    return self._chessCharacter and
        self._chessCharacter:isVisible() and
        self._chessCharacter:containWorldPoint(posX,posY)
end

function FieldManager:testTouchChessCharacter(posX, posY)
    if self:isTouchChessCharacter(posX, posY) then
        local baseInfo = self._chessCharacter:getUserBaseInfo()
        local params = {}
        params.online = true
        params.attr = baseInfo
        params.pos = cc.p(posX, posY)
        params.type = Enums.MenuType.chess
        UIHandler:showHeadMenu(params)
    end
end

function FieldManager:setTargetX(tarx)
    if not tarx then return end
    local character = self._myCharacter
    if not character then return end

    character:setTargetX(tarx)
end

function FieldManager:moveControl(dirFlag)
    if NpcManager:isNpcExcuteEvents() then return end
    if self:isStopTouches() then return end
    if not self._myCharacter then return end

    if dirFlag == Enums.MoveFlag.left then
        -- self:setTargetX(self._myCharacter:getLineMinX())
        self:setTargetX(-99999)
    elseif dirFlag == Enums.MoveFlag.right then
        -- self:setTargetX(self._myCharacter:getLineMaxX())
        self:setTargetX(99999)
    elseif dirFlag == Enums.MoveFlag.stop then
        self:setTargetX(self:getCharacterX())
    end
    -- 清除追踪数据
    self:breakTransfer()
    self:touchEndOperate()
end

function FieldManager:addUserToQueue(entityInfo)
    if not self:isUserInQueue(entityInfo.entityId) then
        if entityInfo.prior then
            table.insert(self._queueEntityInfos, entityInfo)
        else
            table.insert(self._queueEntityInfos, 1, entityInfo)
        end
    end
end

function FieldManager:deleteEntityInfoFromQueue(uid)
    for i = #self._queueEntityInfos,1,-1 do
        if self._queueEntityInfos[i].entityId == uid then
            table.remove(self._queueEntityInfos, i)
        end
    end
end

function FieldManager:isUserInQueue(uid)
    for i, entityInfo in ipairs(self._queueEntityInfos) do
        if entityInfo.entityId == uid then
            return true
        end
    end
    return false
end

function FieldManager:getLastQueueEntityInfo()
    local lastQueueEntityInfo = self._queueEntityInfos[#self._queueEntityInfos]
    return lastQueueEntityInfo
end

function FieldManager:getPartnerRandomTalk(pId)
    local talks = {}
    local partnerConfig = GD:queryPartnerById(pId)
    if partnerConfig and partnerConfig.partnerTalk then
        local privateTalkArray = string.split(partnerConfig.partnerTalk,";")
        if #privateTalkArray > 0 then
            table.insert(talks,privateTalkArray[math.random(1,#privateTalkArray)])
        end
    end
    if partnerConfig and partnerConfig.commonTalk then
        local commonTalkArray = string.split(partnerConfig.commonTalk,";")
        if #commonTalkArray > 0 then
            table.insert(talks,commonTalkArray[math.random(1,#commonTalkArray)])
        end
    end
    local talkString = ""
    if #talks > 0 then
        talkString = L(talks[math.random(1,#talks)])
    end
    return talkString
end

---------------------------佣兵角色数据---------------------------------------

function FieldManager:addFollowMercenary(mercenary, parentUid)
    if not self._followMercenarys[parentUid] then self._followMercenarys[parentUid] = {} end
    if not self._followMercenarys[parentUid][mercenary:getId()] then
        self._followMercenarys[parentUid][mercenary:getId()] = mercenary
    end
end

function FieldManager:getFollowMercenarys()
    local followMercenarys = {}
    for _, mercenarys in pairs(self._followMercenarys) do
        for __, mercenary in pairs(mercenarys) do
            table.insert(followMercenarys, mercenary)
        end
    end
    return followMercenarys
end

function FieldManager:clearFollowMercenarys()
    for _, mercenarys in pairs(self._followMercenarys) do
        for __, mercenary in pairs(mercenarys) do
            self:dispatchEvent({name = "map_delete_character", character = mercenary})
        end
    end
    self._followMercenarys = {}
end

function FieldManager:getFollowMercenaryById(parentUid, id)
    return self._followMercenarys[parentUid][id]
end

function FieldManager:removeMercenaryById(parentUid, id)
    if self._followMercenarys[parentUid] and self._followMercenarys[parentUid][id] then
        local merc = self._followMercenarys[parentUid][id]
        self._followMercenarys[parentUid][id] = nil
        self:dispatchEvent({name = "map_delete_character", character = merc})
    end
end

function FieldManager:followMercenaryVisibility(visible)
    for _, mercenarys in pairs(self._followMercenarys) do
        for __, mercenary in pairs(mercenarys) do
            if mercenary:isVisible() ~= visible then
                mercenary:setVisible(visible)
                mercenary:markNodeVisiblity(visible)
                if not visible then
                    mercenary:hideBubble()
                end
            end
        end
    end
end

function FieldManager:singleMercenaryVisibility(mercenary,visible)
    if mercenary then
        if mercenary:isVisible() ~= visible then
            mercenary:setVisible(visible)
            mercenary:markNodeVisiblity(visible)
            if not visible then
                mercenary:hideBubble()
            end
        end
    end
end

function FieldManager:isHideMercenary()
    local curMapConfig = GD:queryMapById(MapManager:getMapId())
    if curMapConfig and ToNumber(curMapConfig.mercenaryShow) == 1 then
        return true
    end
    return false
end

function FieldManager:removeCharacterMercenary(character)
    if cc.isDead(character) then
        return
    end
    local partners = character:getPartners()
    for k, v in pairs(partners) do
        self:removeMercenaryById(character:getUid(),v.ID)
    end

    character:setPartners({})
end

-- 移除多余的随从
function FieldManager:removeRedundantCharacterMercenary(character, maxShowPartnerNum)
    
end

function FieldManager:isCurrentMapNpc(npcId)
    local npcConfig = GD:queryMapNpc(npcId)
    if npcConfig and ToNumber(npcConfig.mapId) == MapManager:getMapId() then
        return true
    end
    return false
end

function FieldManager:isShowPlayers()
    local config = GD:queryMapById(MapManager:getMapId())
    local showPlayers = ToNumber(config.showPlayers) or 0
    if showPlayers > 0 then
        return false
    else
        return true
    end
end

function FieldManager:updateCharacterFollowMercenary(partners,character)
    if not character then return end

    if #partners == 0 then
        self:removeCharacterMercenary(character)
        return
    end


    -- 公会战 不显示随从
    if app:getInst("DynastyMapModel"):isDynastyMap() or UD.csGuildWarData:isCSGuildWarPrepareMap() then
        self:removeCharacterMercenary(character)
        return
    end
    -- 组队跟随时，不显示随从
    if TeamModel:isWithTeam(character:getUid()) then
        self:removeCharacterMercenary(character)
        return
    end

    --  是队长 修正随从数据  根据队伍人数 自动适配随从数目
    if TeamModel:isLeader(character:getUid()) then
        local tempPartners = partners
        partners = {}
        -- 最多显示随从个数
        local maxShowPartnerNum, hasTeam = TeamModel:getMaxPartnerNum()
        if hasTeam then
            if maxShowPartnerNum <= 0 then
                self:removeCharacterMercenary(character)
            else
                for k, v in pairs(tempPartners) do
                    if k <= maxShowPartnerNum then
                        table.insert(partners, v)
                    end
                end
            end
        end
    end

    -- 隐藏非队伍内玩家时 也移除他们的随从
    -- if self._hidingNotTeamCharacter and not TeamModel:isInTeam(character:getUid()) then

    -- 不显示其他玩家随从
    if character:getUid() ~= UD.player.uid and not TeamModel:isInTeam(character:getUid()) then
        self:removeCharacterMercenary(character)
        return
    end

    local oldPartners = character:getPartners()
    local oldPartnersMap = {}
    for k, v in pairs(oldPartners) do
        oldPartnersMap[v.ID] = true
    end

    local newPartnersMap = {}
    for k, v in pairs(partners) do
        newPartnersMap[v.ID] = true
    end


    character:setPartners(partners)
    for k ,v in pairs(oldPartners) do
        if not newPartnersMap[v.ID] then
            self:removeMercenaryById(character:getUid(),v.ID)
        end
    end

    for k ,v in pairs(partners) do
        if not oldPartnersMap[v.ID] then
            local line = character:getLine()
            local parentUid = character:getUid()
            local merc = Mercenary.new(v.ID,v.ID, nil, true)
            merc:setBelongUid(parentUid)
            merc:setLine(line)
            merc:setLeaderCharacter(character)
            merc:showLocation(character:getPositionX(),character:getPositionY())
            merc:excuteAction(cc.FadeIn:create(0.5))
            self:addFollowMercenary(merc,parentUid)
            self:dispatchEvent({name = "map_add_mercenary",merc = merc})
        else
            local merc = self:getFollowMercenaryById(character:getUid(), v.ID)
            if merc and merc:getLine() ~= character:getLine() then
                MapManager:getMap():changeLine(merc, character:getLine())
            end
        end
    end

    -- if character:getPartnerId() ~= partnerId then
    --     self:removeCharacterMercenary(character)
    --     local npcId = GD:getPartnerNpcIdByPartnerId(partnerId,quality)
    --     local line = character:getLine()
    --     local parentUid = character:getUid()
    --     local merc = Mercenary.new(npcId,partnerId)
    --     merc:setBelongUid(parentUid)
    --     merc:setLine(line)
    --     merc:setLeaderCharacter(character)
    --     merc:showLocation(character:getPositionX(),character:getPositionY())
    --     merc:excuteAction(cc.FadeIn:create(0.5))
    --     self:addFollowMercenary(merc,parentUid)
    --     self:dispatchEvent({name = "map_add_mercenary",merc = merc})
    -- else
    --     -- 佣兵是否和所属的人物在同一层上面
    --     local merc = self:getFollowMercenaryById(character:getUid(), character:getPartnerId())
    --     if merc and merc:getLine() ~= character:getLine() then
    --         MapManager:getMap():changeLine(merc, character:getLine())
    --     end
    -- end
end

function FieldManager:updateSingleMercPosition(mercenary, character, withNum, order)
    if not mercenary or not character then return end

    mercenary:setSpeed(character:getSpeed())
    local leaderDir = character:getDirection()
    local lcx = MathFloor(NodeGetPositionXFunc(character))

    local merx = lcx
    local teamInterval = withNum * Constant.TeamCharacterInterval
    local sInterval = Constant.MercenaryInterval * order
    if leaderDir == character.DIR_LEFT then
        merx = lcx + teamInterval + sInterval
    else
        merx = lcx - teamInterval - sInterval
    end

    if merx < character:getLineMinX() then
        merx = character:getLineMinX()
    end
    if merx > character:getLineMaxX() then
        merx = character:getLineMaxX()
    end

    -- 误差范围以内就跑过去，超过就瞬移过去
    local curPosX = NodeGetPositionXFunc(mercenary)
    if MathAbs(curPosX - merx) <= MERCENARY_ADJUST_DISTANCE then
        mercenary:setTargetX(MathFloor(merx))
    else
        mercenary:showLocationX(merx)
    end
    
end

function FieldManager:updateFollowMercenaryPosition()
    if self:isStopEvent() then
        self:followMercenaryVisibility(false)
    else
        self:followMercenaryVisibility(true)
    end

    -- 我是跟随状态 或者 我是队长 的时候 只更新 队长的宠物位置（队伍满的时候， 队长的也不显示了）
    local withNum = TeamModel:getWithTeamNum(true)
    if TeamModel:isWithTeam() or TeamModel:isLeader() then
       -- do nothing
    else
        withNum = 0
    end

    for parentUid, mercenarys in pairs(self._followMercenarys) do
        local iCount = 1
        local iWithNum = 0
        if withNum > 0 and TeamModel:isLeader(parentUid) then
            iWithNum = withNum
        end

        for __, mercenary in pairs(mercenarys) do
            if mercenary:isVisible() then
                local character = self:getCharacterByUid(parentUid)
                self:updateSingleMercPosition(mercenary, character, iWithNum, iCount)
                iCount = iCount + 1
            end
        end
    end

    local followNum = table.nums(self._followMercenarys[UD:getUid()])
    local taskFollowNum = table.nums(self._selfTaskFollowMercenarys)
    if taskFollowNum > 0 then
        local fNum = followNum
        local count = fNum + 1
        for _, mercenary in pairs(self._selfTaskFollowMercenarys) do
            if mercenary:isVisible() then
                local belongUid = mercenary:getBelongUid()
                local character = self:getCharacterByUid(belongUid)
                self:updateSingleMercPosition(mercenary, character, withNum, count)
                count = count + 1
            end
        end
    end

    local teamFollowNum = table.nums(self._teamTaskFollowMercenarys)
    if teamFollowNum > 0 then
        local fNum = followNum + taskFollowNum
        local count = fNum + 1
        for k,mercenary in pairs(self._teamTaskFollowMercenarys) do
            if mercenary:isVisible() then
                local belongUid = mercenary:getBelongUid()
                local character = self:getCharacterByUid(belongUid)
                self:updateSingleMercPosition(mercenary, character, withNum, count)
                count = count + 1
            end
        end
    end

    local totalNum = followNum + taskFollowNum + teamFollowNum

    self:updateFollowNpcPosition(withNum, totalNum)
end

function FieldManager:showTaskFollowMercenarys()
    self:showSelfTaskFollowMercenarys()
    self:showTeamTaskFollowMercenarys()
end

function FieldManager:hideTaskFollowMercenarys()
    self:hideSelfTaskFollowMercenarys()
    self:hideTeamTaskFollowMercenarys()
end

function FieldManager:createTaskMercenary(info,character,isSelf,deleteCall)
    -- 星空谜棋，不带任务随从
    if app:sendMsg("ChessModel", "isChessMap") then deleteCall() return end
    if app:sendMsg("TheatreModel", "isTheatreMap") then deleteCall() return end
    if app:sendMsg("DynastyMapModel", "isDynastyMap") then deleteCall() return end
    if  UD.csGuildWarData:isCSGuildWarPrepareMap() then deleteCall() return end
   


    if not info or not character then deleteCall() return end
    local task = UD:getTaskById(info.mainTaskID)
    if not task then deleteCall() return end
    if not task:getConfig() then deleteCall() return end
    local storyPartner = task:getConfig().storyPartner
    if not storyPartner then deleteCall() return end

    -- 在地下城里的时候需要 判断当前地图ID，是否和任务所需的地图ID一致
    if DungeonManager:isInDungeon() then
        if MapManager:getMapId() ~= tonumber(task:getConfig().map) then
            deleteCall()
            return
        else
            if not DungeonManager:isTaskDungeon() then -- 地图ID相同判断是否为 假副本
                deleteCall()
                return
            end
        end
    end

    local mercs = {}
    local array = string.split(storyPartner,";")
    for i,v in ipairs(array) do
        local pArray = string.split(v,"|")
        local npcId
        local merc
        if #pArray >= 2 then
            npcId = tonumber(pArray[1])
            local function createMerc()
                local line = character:getLine()
                merc = Mercenary.new(npcId,npcId)
                merc:setBelongUid(info.uid)
                merc:setNameNode(NodeFactory:createHeadName()) -- 给任务随从添加名字
                merc:setLine(line)
                merc:setLeaderCharacter(character)
                merc:showLocation(character:getPositionX(),character:getPositionY())
                merc:excuteAction(cc.FadeIn:create(0.5))
                self:dispatchEvent({name = "map_add_mercenary",merc = merc})
            end
            if isSelf then
                if not self:getSelfTaskFollowMercenary(npcId) then
                    createMerc()
                else
                    merc = self:getSelfTaskFollowMercenary(npcId)
                end
            else
                if not self:isTeamTaskFollowMercenary(npcId) then
                    createMerc()
                else
                    merc = self:isTeamTaskFollowMercenary(npcId)
                    MapManager:getMap():changeLine(merc, character:getLine())
                    merc:setBelongUid(info.uid)
                end
            end
            if npcId and merc then
                table.insert(mercs,{npcId = npcId,merc = merc})
            end
        end
    end
    return mercs
end

function FieldManager:updateSelfTaskFollowMercenary(baseInfo)
    if not baseInfo or baseInfo.uid ~= UD:getUid() then return end
    local character = self._myCharacter
    if not character then return end

    if TeamModel:isInTeam() then -- 只要在队伍里就只显示组队任务随从
        self:removeSelfTaskFollowMercenary()
    else
        self:removeTeamTaskFollowMercenary()
        local mercs = self:createTaskMercenary(baseInfo, character, true, function()
            self:removeSelfTaskFollowMercenary()
        end)
        if mercs then
            local newMercIds = {}
            for i,v in ipairs(mercs) do
                self:addSelfTaskFollowMercenary(v.npcId,v.merc)
                newMercIds[v.npcId] = true
            end
            local temp = clone(self._selfTaskFollowMercenarys)
            for npcId, merc in pairs(temp) do
                if not newMercIds[npcId] then
                    self:deleteSelfTaskFollowMercenary(npcId)
                end
            end
        end
    end
end

function FieldManager:getSelfTaskFollowMercenary(id)
    return self._selfTaskFollowMercenarys[id]
end

function FieldManager:addSelfTaskFollowMercenary(id,merc)
    self._selfTaskFollowMercenarys[id] = merc
end

function FieldManager:deleteSelfTaskFollowMercenary(id)
    if not cc.isDead(self._selfTaskFollowMercenarys[id]) then
        self:dispatchEvent({name = "map_delete_character",character = self._selfTaskFollowMercenarys[id]})
        self._selfTaskFollowMercenarys[id] = nil
    end
end

function FieldManager:removeSelfTaskFollowMercenary()
    for _,merc in pairs(self._selfTaskFollowMercenarys) do
        self:dispatchEvent({name = "map_delete_character",character = merc})
    end
    self._selfTaskFollowMercenarys = {}
end

function FieldManager:showSelfTaskFollowMercenarys()
    for _,merc in pairs(self._selfTaskFollowMercenarys) do
        -- merc:setVisible(true)
        merc:setNodeVisible(true)
    end
end

function FieldManager:hideSelfTaskFollowMercenarys()
    for _,merc in pairs(self._selfTaskFollowMercenarys) do
        -- merc:setVisible(false)
        merc:setNodeVisible(false)
    end
end

function FieldManager:updateTeamTaskFollowMercenary()
    if not TeamModel:isInTeam() then
        self:removeTeamTaskFollowMercenary()
        return
    end
    self:removeSelfTaskFollowMercenary()

    local leaderUid = TeamModel:getLeaderUid()
    local info = self:getBaseInfoById( leaderUid )
    local character = self:getCharacterByUid( leaderUid )

    -- 方案1，自己是队长显示，不是队长不显示(暂时用方案1)
    -- 方案2，自己和队长同任务显示，否则不显示
    if not TeamModel:isLeader() then
        self:removeTeamTaskFollowMercenary()
        return
    end

    local mercs = self:createTaskMercenary(info, character, false, function()
        self:removeTeamTaskFollowMercenary()
    end)

    if mercs then
        local newMercIds = {}
        for i,v in ipairs(mercs) do
            self:addTeamTaskFollowMercenary(v.npcId,v.merc)
            newMercIds[v.npcId] = true
        end
        local temp = clone(self._teamTaskFollowMercenarys)
        for npcId, merc in pairs(temp) do
            if not newMercIds[npcId] then
                self:deleteTeamTaskFollowMercenary(npcId)
            end
        end
    end
end

function FieldManager:isTeamTaskFollowMercenary(id)
    return self._teamTaskFollowMercenarys[id]
end

function FieldManager:addTeamTaskFollowMercenary(id,merc)
    self._teamTaskFollowMercenarys[id] = merc
end

function FieldManager:deleteTeamTaskFollowMercenary(id)
    if not cc.isDead(self._teamTaskFollowMercenarys[id]) then
        self:dispatchEvent({name = "map_delete_character",character = self._teamTaskFollowMercenarys[id]})
        self._teamTaskFollowMercenarys[id] = nil
    end
end

function FieldManager:removeTeamTaskFollowMercenary()
    for _,merc in pairs(self._teamTaskFollowMercenarys) do
        self:dispatchEvent({name = "map_delete_character",character = merc})
    end
    self._teamTaskFollowMercenarys = {}
end

function FieldManager:hideTeamTaskFollowMercenarys()
    for _,merc in pairs(self._teamTaskFollowMercenarys) do
        -- merc:setVisible(false)
        merc:setNodeVisible(false)
    end
end

function FieldManager:showTeamTaskFollowMercenarys()
    for _,merc in pairs(self._teamTaskFollowMercenarys) do
        -- merc:setVisible(true)
        merc:setNodeVisible(true)
    end
end

function FieldManager:countFollowNpcBattlePoints(task,mapId,x)
    if not task then return end
    self._fllowNpcTargetInfo = {taskId = task:getId(), mapId = mapId, x = x}
    self._fllowNpcBattlePoints = TaskManager:getBattlePoints(task)
end

function FieldManager:isNpcFollow(npcId)
    for i,v in ipairs(self._followNpcs) do
        if npcId == v then
            return true
        end
    end
    return false
end

function FieldManager:addFollowNpc(npcId)
    if not self:isNpcFollow(npcId) then
        table.insert(self._followNpcs,npcId)
    end
end

function FieldManager:clearFollowNpc()
    if not self._followNpcs then return end
    for i,v in ipairs(self._followNpcs) do
        NpcManager:deleteNpcById(v)
    end
    self._followNpcs = {}
    self._fllowNpcTargetInfo = nil
    self._fllowNpcBattlePoints = nil
end

function FieldManager:updateFollowNpcPosition(withNum, totalNum)
    if #self._followNpcs == 0 then return end
    if not self._fllowNpcTargetInfo then return end
    if not self._fllowNpcBattlePoints then return end
    if not self._myCharacter then return end

    local targetInfo = self._fllowNpcTargetInfo
    local character = self._myCharacter
    local cx = MathFloor(NodeGetPositionXFunc(character))

    -- 跟随状态下，隐藏自己的任务npc
    local bShow = true
    if TeamModel:isWithTeam() then bShow = false end
    for i, id in ipairs(self._followNpcs) do
        local npc = NpcManager:getNpcById(id)
        if npc then npc:setVisible(bShow) end
    end
    if not bShow then return end

    for i,v in ipairs(self._followNpcs) do
        local npc = NpcManager:getNpcById(v)
        if npc then
            npc:setSpeed(character:getSpeed())
            local leaderDir = character:getDirection()
            local tx
            if leaderDir == character.DIR_LEFT then
                tx = cx + Constant.TeamCharacterInterval * withNum + Constant.MercenaryInterval * totalNum + Constant.MercenaryInterval * i
                npc:setDirection(character.DIR_LEFT)
            else
                 tx = cx - Constant.TeamCharacterInterval * withNum - Constant.MercenaryInterval * totalNum - Constant.MercenaryInterval  * i
                npc:setDirection(character.DIR_RIGHT)
            end

            if tx < character:getLineMinX() then
                tx = character:getLineMinX()
            end
            if tx > character:getLineMaxX() then
                tx = character:getLineMaxX()
            end
            local nx = MathFloor(NodeGetPositionXFunc(npc))
            tx = MathFloor(tx)

            -- 误差范围以内就跑过去，超过就瞬移过去
            if MathAbs(nx - tx) > MERCENARY_ADJUST_DISTANCE then
                npc:showLocationX(tx)
            else
                if nx ~= tx then
                    npc:setTargetX(tx)
                else
                    npc:standBy()
                    npc:faceToCharacter(character)
                end
            end 

        end
    end

    if not targetInfo.finished and targetInfo.mapId == MapManager:getMapId() then
        if cx >= targetInfo.x - 50 and cx <= targetInfo.x + 50 then
            targetInfo.finished = true
            TaskManager:C2S_TaskEscortRequest(targetInfo.taskId, self._followNpcs[1], function()
                self:clearFollowNpc()
            end)
        end
    end

    if self._fllowNpcBattlePoints then
        for i,v in ipairs(self._fllowNpcBattlePoints) do
            if not v.finished then
                if cx >= v.x - v.radius and cx <= v.x + v.radius then
                    v.finished = true
                    -- 跟随状态在上面已经判断
                    BattleManager:storyBattleStart({battleId = v.battleId,mineId = v.mine,x = cx,callback = function(msg) end})
                end
            end
        end
    end
end

function FieldManager:isNoTaskTrack()
    if DoEventHandler.isDoGatherAction()
        or self:isTrackDoing()
        or self:isStopEvent()
    then
        return true
    end
    return false
end

function FieldManager:isStopTeamTouch()
    if TeamModel:isWithTeam() and (not TeamModel:isLeader()) then
        return true
    end
    return false
end

function FieldManager:taskTrackingAutoWayFinding(npcId,trackTaskId,autoStartEvents,isTracking,isLegionTrack,immediately)
    --print("===========> npcId", npcId, trackTaskId)
    self:saveAutoWayParams(nil)

    if TeamModel:isWithTeam() and (not TeamModel:isLeader()) then
        app:popMessage("inteamtaskchasingunavailable")
        return false,true
    end

    if self:isNoTaskTrack() then return end
    if self:isStopTeamTouch() then return end
    if not npcId then return end

    local npc
    local mapNpc
    if type(npcId) ~= "userdata"
      and type(npcId) ~= "table" then
        npcId = ToNumber(npcId)

        local autoPatrol = false
        local nFindNpc = false
        if npcId == 1 then
            nFindNpc = true
            npcId = GD:queryNearbyOreIdByType(3, MapManager:getMapId(),self:getOwnerX())
        elseif npcId == 2 then
            if not UD:isHaveToolByMainType(1) then
                app:popMessage("functionclosed")
                return false,true
            end
            nFindNpc = true
            npcId = UD:getNearestResourcePointByType(1,MapManager:getMapId(),self:getOwnerX())
        elseif npcId == 3 then
            if not UD:isHaveToolByMainType(3) then
                app:popMessage("functionclosed")
                return false,true
            end
            nFindNpc = true
            npcId = UD:getNearestResourcePointByType(5,MapManager:getMapId(),self:getOwnerX())
        elseif npcId == 4 then
            if not UD:isHaveToolByMainType(2) then
                app:popMessage("functionclosed")
                return false,true
            end
            nFindNpc = true
            npcId = UD:getNearestResourcePointByType(2,MapManager:getMapId(),self:getOwnerX())
        elseif npcId == 5 then
            -- nFindNpc = true
            -- npcId = GD:getRandomNpcIdByTrackQuest()
            -- autoPatrol = true
            -- if not npcId then
            --     app:popMessage("trackNpcNotShow")
            --     return false,true
            -- end
        elseif npcId == 6 then
            nFindNpc = true
            npcId = GD:queryNearbyNpcIdByFunction(8,MapManager:getMapId(),self:getOwnerX())
            if not npcId then
                app:popMessage("NoDonateNpc")
                return false,true
            end
        elseif npcId == 9 then
            nFindNpc = true
            for iType = 6,12 do
                npcId = UD:getNearestResourcePointByType(iType,MapManager:getMapId(),self:getOwnerX())
                if npcId then
                    break
                end
            end
            if not npcId then
                app:popMessage("notdisaster")
                return false,true
            end
        elseif npcId == 10 then
            if not UD:isInGuild() then
                app:popMessage("umustjoinaguild")
                return false,true
            end
            nFindNpc = true
            for iType = 20,24 do
                npcId = UD:getNearestResourcePointByType(iType,nil,self:getOwnerX())
                if npcId then
                    break
                end
            end
            if not npcId then
                app:popMessage("guildnotdisaster")
                return false,true
            end
        end

        npc = GD:queryMapNpc(npcId)
        if not npc then
            if nFindNpc then
                app:popMessage("inteamdonotthisthing")
                return false,true
            elseif nFindNpc then
                app:popMessage("mapnotmaterialcollected")
                return false
            end
            return
        end

        if not NpcManager:isCanTrackNpc(npcId) then
            return false,true
        end

        print("taskTrackingAutoWayFinding  npcId = ",npcId)
    end

    local HearthStoneEvent = require("app.scripts.events.HearthStoneEvent")
--    local CameraZoomEvent = require("app.scripts.events.CameraZoomEvent")
    local ChangeMapEvent = require("app.scripts.events.ChangeMapEvent")
    local WalkEvent = require("app.scripts.events.WalkEvent")
    local StartEventsEvent = require("app.scripts.events.StartEventsEvent")
    local AutoPatrolEvent = require("app.scripts.events.AutoPatrolEvent")
    local WaitEvent = require("app.scripts.events.WaitEvent")
    local TransferStatusEvent = require("app.scripts.events.TransferStatusEvent")
    local TransferInSameMapEvent = require("app.scripts.events.TransferInSameMapEvent")

    local destNpcId
    local destMapId
    local destX
    local thunderPatrol
    local thunderRadius
    local mineId

    local task
    if trackTaskId then
        task = UD:getTaskById(trackTaskId)
    end
    if npc then
        destNpcId = ToNumber(npcId)
        destMapId = ToNumber(npc.mapId)
        if task and task:getConfig() then
            local createNpcDelete = task:getConfig().createNpcDelete
            local array = string.split(createNpcDelete,"|")
            if #array >= 3 then
                if ToNumber(array[3]) == destNpcId then
                    destX = NpcManager:getTriggerXToNpc(destNpcId,destMapId,true,ToNumber(array[2]))
                end
            end

        end
        destX = (destX == nil) and NpcManager:getTriggerXToNpc(destNpcId,destMapId,true) or destX
    elseif type(npcId) == "userdata" then
        destMapId = tonumber(npcId.mapId)
        destX = tonumber(npcId.coordinate)
        thunderRadius = tonumber(npcId.talkRadius)
        mineId = tonumber(npcId.ID)
        local mineType = tonumber(npcId.mineType)
        if mineType == 1 then

        end
        thunderPatrol = true
    elseif type(npcId) == "table" then
        destMapId = npcId.mapId
        destX = npcId.x
    end

    local destMapConfig = GD:queryMapById(destMapId)
    if not destMapConfig then return end

    local curMapId = MapManager:getMapId()
    local currentMapConfig = GD:queryMapById(MapManager:getMapId())
    if not currentMapConfig then return end

    -- 如果在剧情副本里 并且 npc 不存在，就提示玩家退出重进（有可能npc是Area类型的）
    -- if destMapId == MapManager:getMapId() and DungeonManager:isInDungeon() and DungeonManager:isTaskDungeon() then
    --     if type(npcId) == "number" and not NpcManager:getNpcById(npcId) then
    --         -- dump(destX)
    --         display.pushToast("npc不存在，请退出重新进入")
    --         return 
    --     end
    -- end

    DoEventHandler.clearEventsStatus()

    if not trackTaskId then
        app:dispatchCustomEvent("EVENT_STOP_TRACKING")
        app:dispatchCustomEvent("EVENT_NPC_TRACK",{start = true,npcId = npcId})
    else
        app:dispatchCustomEvent("EVENT_NPC_TRACK",{start = true,taskId = trackTaskId,npcId = npcId})
    end

    local needDoingEventsVec = Vector.new()

    if destMapId ~= MapManager:getMapId() then
        local function addEventToTrack(events)
            local syncEventsVec = Vector.new()
            for i,v in ipairs(events) do
                local event = v
                syncEventsVec:add(event)
            end
            needDoingEventsVec:add(syncEventsVec)
        end

        local destMapType = ToNumber(destMapConfig.maptype)
        local curMapType = ToNumber(currentMapConfig.maptype)
        local curParentMapId = ToNumber(currentMapConfig.parent)
        local curParentStoneId = ToNumber(currentMapConfig.parentstone)

        local curParentMapId = ToNumber(currentMapConfig.parent)
        local destParentMapId = ToNumber(destMapConfig.parent)
--        print("===========> destParentMapId", destParentMapId)
        local curParentMapConfig
        if curParentMapId then
            curParentMapConfig = GD:queryMapById(curParentMapId)
        end
        local destParentMapConfig
        if destParentMapId then
            destParentMapConfig = GD:queryMapById(destParentMapId)
        end

        local curBornNpcConfig = NpcManager:getNpcConfigById(ToNumber(currentMapConfig.Bornat))

        local curBornatX = NpcManager:getNpcMapCoordinate(ToNumber(currentMapConfig.Bornat))
        local curStoneBornatX = NpcManager:getNpcMapCoordinate(ToNumber(currentMapConfig.stonebornat))
        local curParentBornatX = 0
        if curParentMapConfig then
            curParentBornatX = NpcManager:getNpcMapCoordinate(ToNumber(curParentMapConfig.Bornat))
        end

        local destBornatX = NpcManager:getNpcMapCoordinate(ToNumber(destMapConfig.Bornat))
        local destStoneBornatX = NpcManager:getNpcMapCoordinate(ToNumber(destMapConfig.stonebornat))
        local destParentBornatX = 0
        local destParentStoneBornatX = 0
        local destParentStoneX = 0
        if destParentMapConfig then
            destParentBornatX = NpcManager:getBornPointX(ToNumber(destParentMapConfig.Bornat),destParentMapId,true)
            destParentStoneBornatX = NpcManager:getBornPointX(ToNumber(destParentMapConfig.stonebornat),destParentMapId,false)
            destParentStoneX = NpcManager:getNpcMapCoordinate(ToNumber(destMapConfig.parentstone))
--            print("===========> destParentStoneX", destParentStoneX)
        end

        if destMapType == 1 then--野外
            if curMapType == 1 then--野外（野外－》野外）
                -- print("cur : ", curMapId, curParentMapId)
                -- print("dest: ", destMapId, destParentMapId)

                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else

                    local function startChangeMap(mapId, npcId)
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})

                        local value = {
                            event = "CHANGE_MAP_EVENT",
                            mapId = mapId,
                        }
                        if npcId then 
                            value.confirmNpcId = npcId
                        end
                        local changeMapEvent = ChangeMapEvent.new(value)
                        addEventToTrack({changeMapEvent})
                    end

                    if not curParentMapId and not destParentMapId then -- 主1->主2
                        startChangeMap(destMapId)
                    elseif destParentMapId == curMapId then -- 主1->子1
                        --跑到当前地图的集合石出生点
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneX,dy = 0})
                        addEventToTrack({walkEvent})

                        startChangeMap(destMapId)
                    elseif not curParentMapId then -- 主1->子2
                        startChangeMap(destParentMapId)
                        --跑到 目标地图的父地图 里的集合石出生点
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneX,dy = 0})
                        addEventToTrack({walkEvent})
                        local changeMapEvent2 = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                        addEventToTrack({changeMapEvent2})
                    elseif curParentMapId == destMapId then -- 子1->主1
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                        addEventToTrack({walkEvent})

                        startChangeMap(destMapId, ToNumber(curBornNpcConfig.ID))
                    elseif curParentMapId and not destParentMapId then -- 子1->主2
                        startChangeMap(destMapId)
                    elseif curParentMapId and destParentMapId then -- 子1->子2
                        startChangeMap(destParentMapId)
                        --跑到 目标地图的父地图 里的集合石出生点
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneX,dy = 0})
                        addEventToTrack({walkEvent})
                        local changeMapEvent2 = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                        addEventToTrack({changeMapEvent2})
                    end

                end
            elseif curMapType == 2 then--副本（副本－》野外）
                -- 当前地图是野外的时候，CHANGE_MAP_EVENT会执行退出副本的逻辑
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT"})
                addEventToTrack({changeMapEvent})
                local changeMapEvent1 = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent1})


                -- if curParentMapId == destMapId then--父地图野外
                --     local cbx,confirmNpcId = DungeonManager:getAwayNpcC()
                --     curBornatX = (cbx ~= 0) and cbx or curBornatX
                --     local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                --     addEventToTrack({walkEvent})
                --     local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                --     addEventToTrack({transferStatusEvent})
                --     local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                --     addEventToTrack({hearthStoneEvent})
                --     local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                --     addEventToTrack({transferStatusEvent1})
                --     local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = confirmNpcId,})
                --     addEventToTrack({changeMapEvent})
                -- else--非父地图野外
                --     if immediately then--直接到出生点
                --         local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                --         addEventToTrack({transferStatusEvent})
                --         local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                --         addEventToTrack({hearthStoneEvent})
                --         local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                --         addEventToTrack({transferStatusEvent1})
                --         local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                --         addEventToTrack({changeMapEvent})
                --     else
                --         local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                --         addEventToTrack({walkEvent})
                --         local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                --         addEventToTrack({transferStatusEvent})
                --         local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                --         addEventToTrack({hearthStoneEvent})
                --         local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                --         addEventToTrack({transferStatusEvent1})
                --         local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = curParentMapId,})
                --         addEventToTrack({changeMapEvent})
                --         local waitEvent = WaitEvent.new({event = "WAIT_EVENT",time = 0.05})
                --         addEventToTrack({waitEvent})
                --         local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curParentBornatX,dy = 0})
                --         addEventToTrack({walkEvent})
                --         local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                --         addEventToTrack({transferStatusEvent})
                --         local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                --         addEventToTrack({hearthStoneEvent})
                --         local transferStatusEvent2 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                --         addEventToTrack({transferStatusEvent2})
                --         local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                --         addEventToTrack({changeMapEvent})
                --     end
                -- end
            elseif curMapType == 3 then -- 公会战场
                -- 默认 immediately = true, 不再去跑图
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            elseif curMapType == 4 then--家园（家园－》野外）
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            elseif curMapType == 6 then--公会-野外
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        elseif destMapType == 2 then--副本
            local parentstone = ToNumber(destMapConfig.parentstone)
            local stoneNpcConfig = GD:queryMapNpc(parentstone)
            if stoneNpcConfig then
                destParentStoneBornatX = ToNumber(stoneNpcConfig.coordinate)
            end

            if curMapType == 1 then--野外（野外－》副本）
                if destParentMapId == MapManager:getMapId() then
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = parentstone,})
                    addEventToTrack({changeMapEvent})
                else--即野外到野外
                    if immediately then--直接到出生点
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                        addEventToTrack({changeMapEvent})
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent2 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent2})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = parentstone,})
                        addEventToTrack({changeMapEvent})
                    else--跑到当前地图出生点
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                        addEventToTrack({changeMapEvent})
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = parentstone,})
                        addEventToTrack({changeMapEvent})
                    end
                end
            elseif curMapType == 2 then--副本（副本－》副本）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                    addEventToTrack({changeMapEvent})
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = curParentMapId,})
                    addEventToTrack({changeMapEvent})
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                end
            elseif curMapType == 4 then--家园（家园－》副本）
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                addEventToTrack({changeMapEvent})
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            elseif curMapType == 6 then
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                addEventToTrack({changeMapEvent})
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destParentStoneBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        elseif destMapType == 4 then--家园
            if curMapType == 1 then--野外（野外－》家园）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                end
            elseif curMapType == 2 then--副本（副本－》家园）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                end
            elseif curMapType == 6 then
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        elseif destMapType == 6 then--公会飞船
            if not UD:isInGuild() then
                app:popMessage("enterTheGuildMap")
                return
            end
            if immediately then
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            else
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        end

    else 
        -- 同一张图的时候需要判断能不能从当前点走到目标点（Map表里配有可行走区域）
        local minX = self._myCharacter:getLineMinX()
        local maxX = self._myCharacter:getLineMaxX()
        if destX < minX or destX > maxX then
            local npcs = NpcManager:getNpcVec()

            for uid, lNpc in pairs(npcs) do
                local npcConfig = lNpc:getConfig()
                if npcConfig then
                    local fType = tonumber(npcConfig["function"])
                    local fPar = tonumber(npcConfig["functionPar"])
                    local npcPosX = lNpc:getPositionX()

                    if fType == 54 and npcPosX >= minX and npcPosX <= maxX  then -- 同地图传送 并且 可以从当前点走到该npc的位置
                        -- 判断该npc传送到的点 和 目标点 是否在同一个section
                        if  MapManager:checkInSameSecion(destX, fPar) then

                            local walkEvent = WalkEvent.new({event = "WALK_EVENT", dx = npcPosX, dy = 0})
                            syncEventsVec = Vector.new()
                            syncEventsVec:add(walkEvent)
                            needDoingEventsVec:add(syncEventsVec)
    
                            local transferInSameMapEvent = TransferInSameMapEvent.new({event = "TRANSFER_IN_SAME_MAP_EVENT", npcId = lNpc:getId()})
                            local syncEventsVec = Vector.new()
                            syncEventsVec:add(transferInSameMapEvent)
                            needDoingEventsVec:add(syncEventsVec)
    
                            break
                        end

                    end
                end
            end

        end 
    end

    local waitEvent = WaitEvent.new({event = "WAIT_EVENT",time = 0.05})
    local syncEventsVec = Vector.new()
    syncEventsVec:add(waitEvent)
    needDoingEventsVec:add(syncEventsVec)

    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destX,dy = 0})
    syncEventsVec = Vector.new()
    syncEventsVec:add(walkEvent)
    needDoingEventsVec:add(syncEventsVec)

    if thunderPatrol then
        local autoPatrolEvent = AutoPatrolEvent.new({event = "AUTO_PATROL_EVENT",center = destX,radius = thunderRadius,forever = true})
        local syncEventsVec = Vector.new()
        syncEventsVec:add(autoPatrolEvent)
        needDoingEventsVec:add(syncEventsVec)
    else
        -- if task and task:getConfig() and (tonumber(task:getConfig().condition1Type) ~= 5) then
        if task and task:getConfig() then
            -- 现在把 任务采集也改为自动的
            local startEventsEvent = StartEventsEvent.new({event = "START_EVENTS_EVENT",npcId = destNpcId,taskId = trackTaskId})
            syncEventsVec = Vector.new()
            syncEventsVec:add(startEventsEvent)
            needDoingEventsVec:add(syncEventsVec)
        end
    end

    self:saveAutoWayParams({npcId = npcId,trackTaskId = trackTaskId,autoStartEvents = autoStartEvents,mineId = mineId})
    DoEventHandler.startEvents(needDoingEventsVec)

    if isTracking then
        DoEventHandler.setTracking(true)
    else
        DoEventHandler.setTracking(false)
    end

    self:setTargetInfo({mapId = destMapId,dx = destX})

    return true
end

function FieldManager:getToNpcAutoWayFinding(npcUid, autoStartEvents, immediately)
    self:saveAutoWayParams(nil)

    if self:isStopTeamTouch() then
        app:popMessage("inteamtaskchasingunavailable")
        return false,true
    end

    local npc = NpcManager:getNpcByUid(npcUid)
    if npc == nil then
        npc = UD:getNpcDataByUid(npcUid)
    end
    local mapNpc

    local HearthStoneEvent = require("app.scripts.events.HearthStoneEvent")
    local ChangeMapEvent = require("app.scripts.events.ChangeMapEvent")
    local WalkEvent = require("app.scripts.events.WalkEvent")
    local StartEventsEvent = require("app.scripts.events.StartEventsEvent")
    local AutoPatrolEvent = require("app.scripts.events.AutoPatrolEvent")
    local WaitEvent = require("app.scripts.events.WaitEvent")
    local TransferStatusEvent = require("app.scripts.events.TransferStatusEvent")

    local destNpcId
    local destMapId
    local destX
    local thunderPatrol
    local thunderRadius

    destMapId = ToNumber(npc.mapId) or MapManager:getMapId()
    destX = npc.position or NpcManager:getTriggerXToNpc(destNpcId,destMapId,true)

    local destMapConfig = GD:queryMapById(destMapId)
    local currentMapConfig = GD:queryMapById(MapManager:getMapId())

    DoEventHandler.clearEventsStatus()

    app:dispatchCustomEvent("EVENT_STOP_TRACKING")
    app:dispatchCustomEvent("EVENT_NPC_TRACK",{start = true,npcId = npc.mId})

    local needDoingEventsVec = Vector.new()

    if destMapId ~= MapManager:getMapId() then
        local function addEventToTrack(events)
            local syncEventsVec = Vector.new()
            for i,v in ipairs(events) do
                local event = v
                syncEventsVec:add(event)
            end
            needDoingEventsVec:add(syncEventsVec)
        end

        local destMapType = ToNumber(destMapConfig.maptype)
        local curMapType = ToNumber(currentMapConfig.maptype)
        local curParentStoneId = ToNumber(currentMapConfig.parentstone)

        local curParentMapId = ToNumber(currentMapConfig.parent)
        local destParentMapId = ToNumber(destMapConfig.parent)
        local curParentMapConfig
        if curParentMapId then
            curParentMapConfig = GD:queryMapById(curParentMapId)
        end
        local destParentMapConfig
        if destParentMapId then
            destParentMapConfig = GD:queryMapById(destParentMapId)
        end

        local curBornNpcConfig = NpcManager:getNpcConfigById(ToNumber(currentMapConfig.Bornat))

        local curBornatX = NpcManager:getBornPointX(ToNumber(currentMapConfig.Bornat),MapManager:getMapId(),true)
        local curStoneBornatX = NpcManager:getBornPointX(ToNumber(currentMapConfig.stonebornat),MapManager:getMapId(),false)
        local curParentBornatX = 0
        if curParentMapConfig then
            curParentBornatX = NpcManager:getBornPointX(ToNumber(curParentMapConfig.Bornat),curParentMapId,true)
        end

        local destBornatX = NpcManager:getBornPointX(ToNumber(destMapConfig.Bornat),destMapId,true)
        local destParentBornatX = 0
        local destPatentStoneBornatX = 0
        if destParentMapConfig then
            destParentBornatX = NpcManager:getBornPointX(ToNumber(destParentMapConfig.Bornat),destParentMapId,true)
            destPatentStoneBornatX = NpcManager:getBornPointX(ToNumber(destParentMapConfig.stonebornat),destParentMapId,false)
        end

        if destMapType == 1 then--野外
            if curMapType == 1 then--野外（野外－》野外）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else--跑到当前地图出生点
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    if ToNumber(curBornNpcConfig["function"]) == 51 then
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = ToNumber(curBornNpcConfig.ID)})
                        addEventToTrack({changeMapEvent})
                    else
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                        addEventToTrack({changeMapEvent})
                    end
                end
            elseif curMapType == 2 then--副本（副本－》野外）
                if curParentMapId == destMapId then--父地图野外
                    local cbx,confirmNpcId = DungeonManager:getAwayNpcC()
                    curBornatX = (cbx ~= 0) and cbx or curBornatX
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = confirmNpcId,})
                    addEventToTrack({changeMapEvent})
                else--非父地图野外
                    if immediately then--直接到出生点
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                        addEventToTrack({changeMapEvent})
                    else
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = curParentMapId,})
                        addEventToTrack({changeMapEvent})
                        local waitEvent = WaitEvent.new({event = "WAIT_EVENT",time = 0.05})
                        addEventToTrack({waitEvent})
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curParentBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent2 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent2})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                        addEventToTrack({changeMapEvent})
                    end
                end
            elseif curMapType == 4 then--家园（家园－》野外）
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            elseif curMapType == 6 then--公会-野外
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        elseif destMapType == 2 then--副本
            local parentstone = ToNumber(destMapConfig.parentstone)
            local stoneNpcConfig = GD:queryMapNpc(parentstone)
            if stoneNpcConfig then
                destPatentStoneBornatX = ToNumber(stoneNpcConfig.coordinate)
            end

            if curMapType == 1 then--野外（野外－》副本）
                if destParentMapId == MapManager:getMapId() then
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = parentstone,})
                    addEventToTrack({changeMapEvent})
                else--即野外到野外
                    if immediately then--直接到出生点
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                        addEventToTrack({changeMapEvent})
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent2 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent2})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = parentstone,})
                        addEventToTrack({changeMapEvent})
                    else--跑到当前地图出生点
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                        addEventToTrack({changeMapEvent})
                        local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                        addEventToTrack({walkEvent})
                        local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                        addEventToTrack({transferStatusEvent})
                        local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                        addEventToTrack({hearthStoneEvent})
                        local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                        addEventToTrack({transferStatusEvent1})
                        local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,confirmNpcId = parentstone,})
                        addEventToTrack({changeMapEvent})
                    end
                end
            elseif curMapType == 2 then--副本（副本－》副本）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                    addEventToTrack({changeMapEvent})
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = curParentMapId,})
                    addEventToTrack({changeMapEvent})
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                end
            elseif curMapType == 4 then--家园（家园－》副本）
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                addEventToTrack({changeMapEvent})
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            elseif curMapType == 6 then
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destParentMapId,})
                addEventToTrack({changeMapEvent})
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destPatentStoneBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        elseif destMapType == 4 then--家园
            if curMapType == 1 then--野外（野外－》家园）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                end
            elseif curMapType == 2 then--副本（副本－》家园）
                if immediately then--直接到出生点
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                else
                    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                    addEventToTrack({walkEvent})
                    local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                    addEventToTrack({transferStatusEvent})
                    local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                    addEventToTrack({hearthStoneEvent})
                    local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                    addEventToTrack({transferStatusEvent1})
                    local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                    addEventToTrack({changeMapEvent})
                end
            elseif curMapType == 6 then
                local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = curBornatX,dy = 0})
                addEventToTrack({walkEvent})
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        elseif destMapType == 6 then--公会飞船
            if not UD:isInGuild() then
                app:popMessage("enterTheGuildMap")
                return
            end
            if immediately then
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = true})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            else
                local transferStatusEvent = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = true})
                addEventToTrack({transferStatusEvent})
                local hearthStoneEvent = HearthStoneEvent.new({event = "HEARTH_STONE_EVENT",playAction = false})
                addEventToTrack({hearthStoneEvent})
                local transferStatusEvent1 = TransferStatusEvent.new({event = "TRANSFER_STATUS_EVENT",start = false})
                addEventToTrack({transferStatusEvent1})
                local changeMapEvent = ChangeMapEvent.new({event = "CHANGE_MAP_EVENT",mapId = destMapId,})
                addEventToTrack({changeMapEvent})
            end
        end
    end

    local waitEvent = WaitEvent.new({event = "WAIT_EVENT",time = 0.05})
    local syncEventsVec = Vector.new()
    syncEventsVec:add(waitEvent)
    needDoingEventsVec:add(syncEventsVec)

    local walkEvent = WalkEvent.new({event = "WALK_EVENT",dx = destX, dy = 0})
    syncEventsVec = Vector.new()
    syncEventsVec:add(walkEvent)
    needDoingEventsVec:add(syncEventsVec)

    if thunderPatrol then
        local autoPatrolEvent = AutoPatrolEvent.new({event = "AUTO_PATROL_EVENT",center = destX,radius = thunderRadius,forever = true})
        local syncEventsVec = Vector.new()
        syncEventsVec:add(autoPatrolEvent)
        needDoingEventsVec:add(syncEventsVec)
    end

    self:saveAutoWayParams({npcUid = npcUid, autoStartEvents = autoStartEvents,})
    DoEventHandler.startEvents(needDoingEventsVec)

    if isTracking then
        DoEventHandler.setTracking(true)
    else
        DoEventHandler.setTracking(false)
    end

    self:setTargetInfo({mapId = destMapId,dx = destX})

    return true
end

function FieldManager:hideAllBubble()

    if self._myCharacter then
        self._myCharacter:hideBubble()
    end
    local puppetCharacter = self:getPuppetCharacter()
    if puppetCharacter then
        puppetCharacter:hideBubble()
    end

    local npcVec = NpcManager:getNpcVec()
    for k,npc in pairs(npcVec) do
        if npc then
            if npc:getId() ~= DoEventHandler.getCurrentEventNpcId() then
                npc:setDoingEvents(false)
            end
            npc:hideBubble()
        end
    end
end

function FieldManager:setTransferring(isTransferring)
    self._transferring = isTransferring
    if isTransferring then
        NpcManager:allNpcUpHeadNodeVisibility(false)
    end
end

function FieldManager:isTransferring()
    return self._transferring
end

function FieldManager:setTransferStart(isStart)
    self._transferStart = isStart
end

function FieldManager:isTransferStart()
    return self._transferStart
end

function FieldManager:setTrackDoing(isDoing)
    self._trackDoing = isDoing
end

function FieldManager:isTrackDoing()
    return self._trackDoing
end

function FieldManager:updateTouchLayer(isUpdate)
    if isUpdate then
        self:dispatchEvent({name = "onAddTouchLayer"})
    else
        self:dispatchEvent({name = "onRemoveTouchLayer"})
    end
end

function FieldManager:startUpdateFrame()
    self._updateFrame = true
    self:updateTouchLayer(self._updateFrame)
    self:startTimer()
end

function FieldManager:stopUpdateFrame()
    self._updateFrame = false
    self:updateTouchLayer(self._updateFrame)
    self:stopTimer()
end

function FieldManager:isUpdateFrame()
    return self._updateFrame
end

function FieldManager:updateFrame(dt)
    if not self._updateFrame then
        return
    end
    self:updateCharacters(dt)
    TeamManager_updateTeamPosition(TeamManager)
    NpcManager_updateNpcPlayEvents(NpcManager, dt)
    self:updateMapUsersVisibility()
    DungeonManager_updateFrame(DungeonManager, dt)
    MapManager_updateFrame(MapManager, dt)
    DelayStack_updateFrame(DelayStack, dt)
    self:updateTimer(dt)
    self:updateFollowMercenaryPosition()
end

function FieldManager:updateFrameLower(dt)
    if not self._updateFrame then
        return
    end
    NpcManager_updateNpcLower(NpcManager, dt)
    self:updateQueueCharacters()
    BattleManager_updateDarkThunderBattle(BattleManager, dt)
end

function FieldManager:startTimer()
    self.mStartTimer = true
    self.lastSyncPosTime = 0
    self._lastMoveSyncPosTime = 0
    self._characterIsMoving = false
    self.mQueryTime = 0
end

function FieldManager:stopTimer()
    self.mStartTimer = false
end

function FieldManager:resetTimer()
    self.lastSyncPosTime = app:getTime()
end

function FieldManager:updateTimer(dt)
    if not self.mStartTimer then return end

    local character = self._myCharacter
    if character then
        if not character:isMove() then return end
        local curTime = app:getTime()
        local dt = (curTime - self.lastSyncPosTime)*1000

        if dt > SYNC_POS_INTERVAL_RUNNING then
            self.lastSyncPosTime = curTime
            -- self:refreshMyCharacterPositionToServer() -- 定时上报打开

            if DEBUG > 0 then
                app:dispatchCustomEvent("temp_pos_desktop_refresh")
            end
        end

        dt = (curTime - self._lastMoveSyncPosTime) * 1000
        if self._characterIsMoving and dt > Constant.SyncCharacterMovePosToServerInterval then
            self._lastMoveSyncPosTime = curTime
            self:reportMyCharacterMovingToServer()
        end
    end
end

function FieldManager:initWeatherSystem()
    local WeatherSystem = app:getClass("WeatherSystem")
    self._weatherSystem = WeatherSystem.new()
end

function FieldManager:getWeatherSystem()
    return self._weatherSystem
end

function FieldManager:isShowUiOperate()
    return self._showUiOperate
end

function FieldManager:showUiOperate()
    self:cameraZoomIn()
    self._showUiOperate = true
    NpcManager:allNpcExceptUiNpcVisibility(false)
end

function FieldManager:removeUiOperate()
--    self:cameraZoomOut()
    self._showUiOperate = false
    NpcManager:allNpcExceptUiNpcVisibility(true)
end

function FieldManager:resetFollowNpcToOriginalPosition()
    if not self:getEscortFollow() then return end
    local npc = NpcManager:getNpcByUid(self:getEscortFollow().npcUid)
    if npc then
        local ox = npc:getOriginalX()
        npc:showLocationX(ox)
        npc:setTargetX(ox)
    end
end

function FieldManager:addGotCalendarNewFunctionId(funcId)
    self._gotCalFuncIds = self._gotCalFuncIds or {}
    self._gotCalFuncIds[funcId] = funcId
end

function FieldManager:deleteGotCalendarNewFunctionId(funcId)
    if self._gotCalFuncIds then
        self._gotCalFuncIds[funcId] = nil
    end
end

function FieldManager:touchEndOperate()
    self:setTargetInfo(nil)
    self:setTrackData(nil)
    DoEventHandler.clearEventsStatus()
    NodeFactory:updateArrowAnimationTimes()
    MapManager:resetMapFocus()
    app:dispatchCustomEvent("EVENT_STOP_TRACKING")
end

-- DoEventHandler 正常执行完事件，追踪完成
function FieldManager:completeEvent()
    if self._trackType then
        if self._trackType == Enums.trackType.wildBoss then
            -- 检查是否是野外boss
            app:sendMsg("SummonBossController", "openView", self._trackData)
        elseif self._trackType == Enums.trackType.worldBoss then
            -- 检查是否是世界boss
            app:sendMsg("WorldBossController", "openView", 2)
        elseif self._trackType == Enums.trackType.dynasty then
            -- 公会战
            app:sendMsg("DynastyBattleController", "openView", {self._trackData})
        end
    end

    self:setTrackData(nil)
end

-- 设置追踪数据，等追踪到目标的是你用来执行相关操作
function FieldManager:setTrackData(type, data)
    self._trackType = type
    self._trackData = data
end

function FieldManager:isHaveGotCalendarNew()
    if self._gotCalFuncIds then
        local count = 0
        for _,v in pairs(self._gotCalFuncIds) do
            count = count + 1
        end
        if count > 0 then
            return true
        else
            return false
        end
    end
    return false
end

function FieldManager:updateUnGotDailyTask(unGot)
    if unGot then
        self:deleteGotCalendarNewFunctionId(Constant.FUNC_TYPE_CALENDAR_CIRCLE_LABEL)

        if UD.badge:getNum(Constant.FUNC_TYPE_CALENDAR_CIRCLE_LABEL) ~= 0 then
            UD.badge:setNum(Constant.FUNC_TYPE_CALENDAR_CIRCLE_LABEL,0)
            -- UD.dirty = true
        end
    else
        self:addGotCalendarNewFunctionId(Constant.FUNC_TYPE_CALENDAR_CIRCLE_LABEL)
        if UD.badge:getNum(Constant.FUNC_TYPE_CALENDAR_CIRCLE_LABEL) ~= 1 then
            UD.badge:setNum(Constant.FUNC_TYPE_CALENDAR_CIRCLE_LABEL,1)
            -- UD.dirty = true
        end
    end
end

function FieldManager:refreshBuff()
    -- if not TeamModel:hasTeam() then return end
    local baseLevel = ToNumber(S("fosterminlv")) or 30
    local disLevel = ToNumber(S("fosterexceedlv")) or 5

    local isWithLegion = TeamModel:isWithLegion()
    local isLeader = TeamModel:isLeader()
    local isWithTeam = TeamModel:isWithTeam()

    if UD:getPlayer().level >= baseLevel then
        local averageTeamLevel = TeamModel:getAverageTeamLevel()
        if UD:getPlayer().level - averageTeamLevel >= disLevel and isWithTeam then
            EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff1)
        else
            EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff1)
        end
    end

    if TeamModel:isHaveSameGuild() and isWithTeam then
        EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff0)
    else
        EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff0)
    end

    EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff7)
    EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff6)
    EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff5)
    EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff4)
    EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff3)

    if isLeader and isWithLegion then
        EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff8)
    else
        EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff8)
    end
    if isLeader and isWithTeam and not isWithLegion then
        local withTeamNums = TeamModel:getWithTeamNum()
        if withTeamNums >= 5 then
            EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff7)
        else
            EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff7)
        end
        if withTeamNums == 4 then
            EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff6)
        else
            EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff6)
        end
        if withTeamNums == 3 then
            EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff5)
        else
            EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff5)
        end
        if withTeamNums == 2 then
            EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff4)
        else
            EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff4)
        end
        if withTeamNums == 1 then
            EM:notify("onAddInfiniteBuffId",Enums.infiniteBuff.buff3)
        else
            EM:notify("onDeleteInfiniteBuffId",Enums.infiniteBuff.buff3)
        end
    end
end

function FieldManager:breakTransfer()
    if StoryManager:isEnterStoryMode() then
        return
    end
    if self:isTransferring() or self:isTransferStart() then
        UIHandler:showDesktop()
        self:setTransferring(false)
        self:setTransferStart(false)
        UIHandler:handleMessage({id = Constant.FUNC_TYPE_TRANSFER,mode = "close"})
        NpcManager:showAllNpcMark()
        NpcManager:resetAllNpcEventStatus()
        NpcManager:clearAllMapNpcDoing()
        -- MapManager:forceCameraZoomToRunMax({resetPause = true})
        app:dispatchCustomEvent("EVENT_STOP_TRACKING")
    end
end

function FieldManager:breakTransferStatus()
    self:setTransferring(false)
    self:setTransferStart(false)
    UIHandler:handleMessage({id = Constant.FUNC_TYPE_TRANSFER,mode = "close"})
    NpcManager:clearAllMapNpcDoing()
end

function FieldManager:breakTransferForStory()
    self:setTransferring(false)
    self:setTransferStart(false)
    UIHandler:handleMessage({id = Constant.FUNC_TYPE_TRANSFER,mode = "close"})
end

function FieldManager:savePatrolParams(save)
    self._patrolParams = nil
    if save then
        local character = self._myCharacter
        if character then
            self._patrolParams = {patrol = true,center = character:getPatrolCenter(),radius = character:getPatrolRadius()}
        end
    end
end

function FieldManager:getPatrolParams()
    return self._patrolParams
end

function FieldManager:goOnPatrol()
    local function patrol(playStatus)
        local patrolParams = self:getPatrolParams()
        if patrolParams and self._myCharacter then
            self._myCharacter:setAutoPatrol(patrolParams.patrol,patrolParams.center,patrolParams.radius)
            if playStatus then
                app:dispatchCustomEvent("EVENT_START_TRACKING_STATUS")
            end
            app:dispatchCustomEvent("EVENT_OPEN_TRACK_LIST")
        end
    end

    local autoPatrolForever = DoEventHandler.isAutoPatrolForever()
    if autoPatrolForever then
        patrol(true)
    else
        if TaskManager:isCurrentTaskIdExsit() then
            local task = UD:getTaskById(TaskManager:getCurrentTrackTaskId())
            if task and task:getConfig() and ToNumber(task:getConfig().scheduleString) == 3 then
                patrol(true)
            end
        end
    end

    self:savePatrolParams(false)
end

function FieldManager:saveTrackingParams(save)
    self._trackingParams = nil
    if save then
        self._trackingParams = {tracking = true}
    end
end

function FieldManager:goOnTracking()
    if self._trackingParams and self._trackingParams.tracking then
        local params = self._autoWayParams
        if params then
            if params.npcId then
                local isFinding = self:taskTrackingAutoWayFinding(params.npcId,params.trackTaskId,params.autoStartEvents,true)
                if isFinding then
                    DoEventHandler.setTracking(true)
                    if params.trackTaskId then
                        app:dispatchCustomEvent("EVENT_START_TRACKING_STATUS")
                        app:dispatchCustomEvent("EVENT_OPEN_TRACK_LIST")
                        app:dispatchCustomEvent("EVENT_NPC_TRACK",{start = true,taskId = params.trackTaskId,npcId = params.npcId})
                    elseif params.npcId then
                        app:dispatchCustomEvent("EVENT_NPC_TRACK",{start = true,npcId = params.npcId})
                    end
                end
            else
                self:getToNpcAutoWayFinding(params.npcUid, params.autoStartEvents)
            end
        end
    end
    self:saveTrackingParams(false)
end

function FieldManager:saveAutoWayFindingParams()
    local character = self._myCharacter
    if character == nil then return end

    local isAutoPatrol = character:isAutoPatrol()
    if isAutoPatrol then
        self:savePatrolParams(true)
    else
        self:savePatrolParams(false)
        if DoEventHandler.isTracking() then
            self:saveTrackingParams(true)
        else
            self:saveTrackingParams(false)
        end
    end
end

function FieldManager:battleCloseTrackList()
    local patrolParams = self:getPatrolParams()
    if patrolParams or (self._trackingParams and self._trackingParams.tracking) then
        app:dispatchCustomEvent("EVENT_CLOSE_TRACK_LIST")
    end
end

function FieldManager:excuteAutoWayFindingParams()
    if StoryManager:isEnterStoryMode() then
        return
    end
    self:goOnPatrol()
    self:goOnTracking()
end

function FieldManager:clearAutoWayFindingParams()
    self:savePatrolParams(false)
    self:saveTrackingParams(false)
    self:saveAutoWayParams(nil)
end

function FieldManager:setTargetInfo(info)
    self._targetInfo = info
end

function FieldManager:getTargetInfo()
    return self._targetInfo
end

function FieldManager:isArriveTarget()
    local character = self._myCharacter
    local targetInfo = self:getTargetInfo()
    if not targetInfo or not character then return end
    if targetInfo.mapId == MapManager:getMapId() and targetInfo.dx + 10 >= NodeGetPositionXFunc(character) and targetInfo.dx - 10 <= NodeGetPositionXFunc(character) then
        return true
    end
    return false
end

function FieldManager:setSecretLayer(layer)
    self._secretLayer = layer
end

function FieldManager:getSecretLayer()
    return self._secretLayer or 0
end

function FieldManager:addSecretBuffId(buffId)
    if not self._secretBuffIds then
        self._secretBuffIds = {}
    end
    self._secretBuffIds[ToString(buffId)] = buffId
end

function FieldManager:clearSecretBuffIds()
    self._secretBuffIds = {}
end

function FieldManager:getSecretBuffIds()
    return self._secretBuffIds or {}
end

function FieldManager:startDebugUsers()
    self._debugUsers = true
end

function FieldManager:stopDebugUsers()
    if not self._debugUsers then return end
    self._debugUsers = false
end

-- function FieldManager:createDebugUser()
--     local entitie = {player = {userBaseInfo = {}}}

--     entitie["player"]["userBaseInfo"].uid = ToString(10000 + self._debugUserCount)
--     print("uid = ",entitie["player"]["userBaseInfo"].uid)

--     entitie["player"]["userBaseInfo"].name = L("lua_code_text_244") .. entitie["player"]["userBaseInfo"].uid
--     entitie["player"]["userBaseInfo"].maskId = 50110100
--     entitie["player"]["userBaseInfo"].titleID = 0
--     entitie["player"]["userBaseInfo"].classId = 1
--     entitie["player"]["userBaseInfo"].guildName = ""
--     entitie["player"]["userBaseInfo"].headId = 60110101
--     entitie["player"]["userBaseInfo"].mercId = 0
--     entitie["player"]["userBaseInfo"].mountId = 0
--     entitie["player"]["userBaseInfo"].raceId = 1

--     entitie["player"].pos = {x = math.random(DEBUG_USERS_STARTX,DEBUG_USERS_ENDX)}
--     entitie["player"].map = {id = MapManager:getMapId(),subId = ""}
--     entitie["player"].visibility = "in"
--     entitie["player"].action = "none"
--     entitie["player"].actionPar1 = ""

--     return entitie
-- end

-- function FieldManager:debugUpdateUsers(dt)
--     if not self._debugUsers then return end
--     if self._debugUserTimeCount * 1000 >= DEBUG_USERS_TIME then
--         self:debugUsersAutoAction()
--         if self._debugUserCount < DEBUG_USERS_MAX then
--             local entities = {}
--             local entitie = self:createDebugUser()
--             table.insert(entities,entitie)
--             self:onParseMapUsersUpdateResponse({entities = entities},true)
--             self._debugUserCount = self._debugUserCount + 1
--         end
--         self._debugUserTimeCount = 0
--     end

--     self._debugUserTimeCount = self._debugUserTimeCount + dt
-- end

function FieldManager:debugUsersAutoAction()
    -- for k,user in pairs(self:getMapUsers()) do
    --     if user:isDebug() then
    --         if user:getDebugDirection() == "r" then
    --             if user.pos.x < DEBUG_USERS_ENDX then
    --                 user.pos.x = user.pos.x + 200
    --             end
    --             if user.pos.x > DEBUG_USERS_ENDX then
    --                 user:setDebugDirection("l")
    --             end
    --         elseif user:getDebugDirection() == "l" then
    --             if user.pos.x > DEBUG_USERS_STARTX then
    --                 user.pos.x = user.pos.x - 200
    --             end
    --             if user.pos.x < DEBUG_USERS_STARTX then
    --                 user:setDebugDirection("r")
    --             end
    --         end
    --         user.visibility = "updated"
    --         user:setUpdate(true)
    --     end
    -- end
end

return FieldManager
